Open In App

React.js Error Boundaries

Last Updated : 04 Apr, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Error Boundaries: Error Boundaries basically provide some sort of boundaries or checks on errors, They are React components that are used to handle JavaScript errors in their child component tree.

React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI. It catches errors during rendering, in lifecycle methods, etc.

Reason to Use: Suppose there is an error in JavaScript inside component then it used to corrupt React’s internal state and cause it to emit cryptic errors. Error boundaries help in removing these errors and display a Fallback UI instead(Which means a display of an error that something broke in the code).

Working Principle: Error Boundary works almost similar to catch in JavaScript. Suppose an error is encountered then what happens is as soon as there is a broken JavaScript part in Rendering or Lifecycle Methods, It tries to find the nearest Error Boundaries Tag.

Creating React Application: 

Step 1: Create a React application using the following command:

create-react-app error-boundary

Step 2: After creating the error-boundary directory move to it.

cd error-boundary

Project Structure: It will look like the following.

Example: Now write down the following code in the App.js file. Here, App is our default component where we have written our code. 

Filename: App.js

Javascript




import React from "react";
  
class ErrorBoundary extends React.Component {
  
  // Constructor for initializing Variables etc in a state
  // Just similar to initial line of useState if you are familiar 
  // with Functional Components
  constructor(props) {
    super(props);
    this.state = { error: null, errorInfo: null };
  }
  
  // This method is called if any error is encountered
  componentDidCatch(error, errorInfo) {
  
    // Catch errors in any components below and
    // re-render with error message
    this.setState({
      error: error,
      errorInfo: errorInfo
    })
  
    // You can also log error messages to an error
    // reporting service here
  }
  
  // This will render this component wherever called
  render() {
    if (this.state.errorInfo) {
  
      // Error path
      return (
        <div>
          <h2>An Error Has Occurred</h2>
          <details>
            {this.state.error && this.state.error.toString()}
            <br />
            {this.state.errorInfo.componentStack}
          </details>
        </div>
      );
    }
    // Normally, just render children, i.e. in 
    // case no error is Found
    return this.props.children;
  }
}
  
  
// This is a component for Counter,Named Counter
class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { counter: 0 };
    this.handleClick = this.handleClick.bind(this);
  }
  
  handleClick() {
    this.setState(({ counter }) => ({
      counter: counter + 1
    }));
  }
  
  render() {
    if (this.state.counter === 3) {
  
      // Simulate a JS error
      throw new Error('Crashed!!!!');
    }
    return <h1 onClick={this.handleClick}>{this.state.counter}</h1>;
  }
}
  
function App() {
  return (
    <div style={{ marginLeft: '30px', marginTop: '50px' }}>
      <div style={{ textAlign: "center" }}>
        <h1>
          <strong>To see the working of Error boundaries
           click on the Counters to increase the value
          </strong>
        </h1>
          
          
  
<p>
          Program is made such a way that as soon as the counter
          reaches the value of 3, Error boundaries will throw an 
          error.
        </p>
  
  
  
      </div>
      <hr style={{ width: "500px" }} />
      <ErrorBoundary>
          
          
  
<p>
          These two counters are inside the same error boundary.
          If one crashes, then the effect will be done on both 
          as the error boundary will replace both of them.
        </p>
  
  
  
        <Counter />
        <Counter />
      </ErrorBoundary>
      <hr style={{ width: "500px" }} />
        
        
  
<p>
        These two counters are each inside of their 
        own error boundary. So if one crashes, the 
        other is not affected.
      </p>
  
  
  
      <ErrorBoundary><Counter /></ErrorBoundary>
      <ErrorBoundary><Counter /></ErrorBoundary>
    </div>
  );
}
  
export default App;


 
Filename: index.js

Javascript




import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
  
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);
  
reportWebVitals();


Step to Run Application: Run the application using the following command from the root directory of the project. 

npm start

Output: Now open your browser and go to http://localhost:3000/, you will see the following output. 

Explanation: The above code is written in such a way that if the counter reaches the value of 3 then Error Boundaries will throw an error.

As shown in the above code that two counters are included in the same Error Boundary Component through which if any one of them causes any sort of error by reaching the value of 3, then instead of rendering any of them a detailed message will be provided on the screen.

On the other end below both counters are included in the individual error Boundaries component through which what happens is only that counter which has caused the error is not rendered, while others are rendered normally.

Error boundaries do not catch errors for the following events:

  • Event Handlers
  • Asynchronous code(Example request Animation Frame etc)
  • Server-Side Rendering
  • Errors are thrown in the error boundary itself (rather than its children)

Try/Catch: One question which might be tickling in your mind is since Error Boundaries works like Catch, Why not just go with try/catch and why should you learn this new Concept. Well, the answer is try/catch is used with imperative code but As we know that React is declarative in nature, and Error Boundaries help in preserving the declarative nature of React.

Uncaught changes: Since it does not catch errors in some particular cases, So what about those errors that left unchecked or Uncaught. As of React 16, errors that were not caught by any error boundary will result in unmounting of the whole React component tree. This means after migrating to React 16 and using Error Boundaries, you will be able to provide a better user experience as now users will be able to see the reason before an unexpected crash, instead of just guessing.

Component Stack Trace: React 16 prints all errors that occurred, it provides component Stack Trace. This helps the user in identifying the point where an error has occurred.

Event Listeners: Error Boundaries does not check errors in event handlers, So should this be counted as some sort of Limitation of Error Boundaries, Well the answer is no, the Reason being Event Listeners does not happen during rendering, So if any error is caused due to them React will simply display it on the screen. 

Error Boundaries:

  • It can only be used with Class Components.
  • It does not catch errors for Event Handlers, Asynchronous code(Example request Animation Frame), Server Side Rendering, and Errors are thrown in the error boundary itself (rather than its children).
  • It is available only in react 16 or after.

Reference: https://reactjs.org/docs/error-boundaries.html

 



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads