Error boundaries are a powerful feature in React that allow developers to catch and handle JavaScript errors gracefully, preventing the entire application from crashing. However, sometimes you may encounter situations where you need to reset an error boundary and recover from an error state. In this blog post, we will explore how to reset an error boundary in React and regain control over error handling.
Before we dive into resetting error boundaries let us quickly recap what error boundaries are.
What is an Error Boundary?
Error boundaries work like a JavaScript catch {} block, but for components. They are React components that implement the componentDidCatch lifecycle method. By defining this method, you can catch errors that occur within the component's tree and display a fallback UI instead of the error propagating to the entire application.
By default, error boundaries will catch errors in the rendering phase. However, they do not catch errors in event handlers, async code (e.g., setTimeout), or during server-side rendering. When an error is caught by an error boundary, React will call the componentDidCatch method, allowing you to handle the error appropriately.
Resetting an Error Boundary
Resetting an Error Boundary becomes necessary in certain scenarios. For example, imagine a form where user is filling up the data and the form has some validation rules. After the user has entered information if application runs into an error because of an invalid input, it would be beneficial to reset the error boundary after displaying an error message. This allows the user to correct the input and submit the form again without having to refresh the page or start from scratch.
To reset an Error Boundary, you need to manipulate its internal state.
class MyErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
this.resetErrorBoundary = this.resetErrorBoundary.bind(this);
}
componentDidCatch(error, errorInfo) {
this.setState({ hasError: true });
}
resetErrorBoundary() {
this.setState({ hasError: false });
}
render() {
if (this.state.hasError) {
return (
<div>
<h1>Something went wrong!</h1>
<button onClick={this.resetErrorBoundary}>Reset</button>
</div>
);
}
return this.props.children;
}
}
Steps to follow:
Create a state variable within your error boundary component to track the error state. For example, you can define a hasError state variable and initialise it to false.
In the componentDidCatch method of the error boundary component, set the hasError state variable to true. This indicates that an error has occurred.
In render function return an appropriate fallback UI to notify the user of the error only when the state hasError is true.
To reset the state, add a Reset button in the fallback UI.
Implement the reset function like resetErrorBoundary defined in the above mentioned code. This function should set the hasError state variable back to false and perform any necessary cleanup or reset actions.
Update Error boundary from outside
To update the error boundary state from outside, you can make use of a React Context. There can be other ways also.
Here’s an example using React context:
- Create an error context to manage the error state and provide a method to update it.
// Error Context Provider
import React, { createContext, useState } from "react";
const ErrorContext = createContext({
hasError: false,
updateError: () => {}
});
const ErrorContextProvider = ({ children }) => {
const [hasError, setHasError] = useState(false);
const updateError = (value) => {
setHasError(value);
};
return (
<ErrorContext.Provider value={{ hasError, updateError }}>
{children}
</ErrorContext.Provider>
);
};
export { ErrorContext, ErrorContextProvider };
- In the error boundary component, access the error context and update the error state when an error occurs.
// Error Context Provider
import React from "react";
import { ErrorContext } from "./ErrorContextProvider";
class ErrorBoundary extends React.Component {
static contextType = ErrorContext;
componentDidCatch(error, errorInfo) {
this.context.updateError(true);
}
render() {
if (this.context.hasError) {
return (
<div>
<h1>Something went wrong!</h1>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundary;
- Wrap your application or the relevant portion of the component tree with the ErrorContextProvider.
import { createRoot } from "react-dom/client";
import { ErrorContextProvider } from "./ErrorContextProvider";
import App from "./App";
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
root.render(
<ErrorContextProvider>
<App />
</ErrorContextProvider>
);
- From a higher-level component or an event handler outside the error boundary component hierarchy, update the error state by accessing the updateError method from the error context. TextField internally throws an error.
import "./styles.css";
import { TextField } from "./TextField";
import ErrorBoundary from "./ErrorBoundary";
import { useContext } from "react";
import { ErrorContext } from "./ErrorContextProvider";
export default function App() {
const { updateError } = useContext(ErrorContext);
const handleReset = () => {
updateError(false);
};
return (
<div className="App">
<div>
<button onClick={handleReset}>Reset boundary</button>
</div>
<ErrorBoundary>
<TextField />
</ErrorBoundary>
</div>
);
}
Codesandbox : https://codesandbox.io/s/reset-error-boundary-wk86wj
Hope this helps. Happy coding! :D
Top comments (1)
I wonder if I can "Update Error boundary from outside" with the react-error-boundary library(github.com/bvaughn/react-error-bou...).