In React, Error Boundaries are a way to catch and handle errors that occur during the rendering process of a component tree. This helps to prevent the entire application from crashing due to a single error. In this article, we'll go over the basics of Error Boundaries and provide an example of how to use them in a React component.
Let's start by creating a new React component called "ErrorBoundary" that will be our error boundary. The ErrorBoundary component will have a state property called "hasError" that will be set to false by default. If an error occurs during the rendering process of its child components, the "hasError" property will be set to true and an error message will be displayed to the user.
Here is the code for the ErrorBoundary component:
import React from "react";
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
export default ErrorBoundary;
In this code, we define the ErrorBoundary component as a class component. In its constructor, we set the initial state of "hasError" to false.
The getDerivedStateFromError()
is a lifecycle method that is called whenever an error is thrown by the child components of the ErrorBoundary. It returns a new state that will update the hasError
property to true.
In the render()
method, we check if the hasError
property is true. If it is, we display an error message. Otherwise, we return the child components of the ErrorBoundary using the props.children
property.
Now, let's create a child component called "Counter" that will simply display a number and increment it when a button is clicked.
import React from "react";
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState((state) => ({ count: state.count + 1 }));
}
render() {
if (this.state.count === 5) {
throw new Error("Oops!");
}
return (
<div>
<h2>Count: {this.state.count}</h2>
<button onClick={this.handleClick}>Increment</button>
</div>
);
}
}
export default Counter;
In this code, we define the Counter component as a class component. In its constructor, we set the initial state of "count" to 0 and bind the handleClick()
method to the component's this
context.
In the render()
method, we check if the count
property is equal to 5. If it is, we throw an error by using the throw
keyword with a new Error object.
Now, let's use these components in a parent component called "App" and wrap the Counter component inside the ErrorBoundary component.
import React from "react";
import ErrorBoundary from "./ErrorBoundary";
import Counter from "./Counter";
const App = () => {
return (
<div>
<ErrorBoundary>
<Counter />
</ErrorBoundary>
</div>
);
};
export default App;
In this code, we import both the ErrorBoundary and Counter components and wrap the Counter component inside the ErrorBoundary component. This means that if an error is thrown by the Counter component, it will be caught by the ErrorBoundary and the error message will be displayed instead of crashing the entire application.
To replicate this example in your local machine, follow these steps:
Create a new React project by running the following command in your terminal:
npx create-react-app my-app
Change your directory to the newly created project by running the following command:
cd my-app
Replace the contents of the
src
folder with the following files:src/App.js
import React from "react"; import ErrorBoundary from "./ErrorBoundary"; import Counter from "./Counter"; const App = () => { return ( <div> <ErrorBoundary> <Counter /> </ErrorBoundary> </div> ); }; export default App;
src/ErrorBoundary.js
import React from "react"; class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } render() { if (this.state.hasError) { return <h1>Something went wrong.</h1>; } return this.props.children; } } export default ErrorBoundary;
src/Counter.js
import React from "react"; class Counter extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState((state) => ({ count: state.count + 1 })); } render() { if (this.state.count === 5) { throw new Error("Oops!"); } return ( <div> <h2>Count: {this.state.count}</h2> <button onClick={this.handleClick}>Increment</button> </div> ); } } export default Counter;
Start the development server by running the following command:
npm start
Open your browser and navigate to localhost:3000 to see the application in action.
Application Screenshots
In conclusion, Error Boundaries are an important tool for handling errors in React applications. They allow us to catch and handle errors that occur during the rendering process of a component tree, preventing the entire application from crashing due to a single error. By following the example provided in this article, you can easily incorporate Error Boundaries into your own React projects.