How to Update Error Boundaries in React
React Error Boundaries are essential tools for catching JavaScript
errors in child component trees, preventing the entire application from
crashing. This article explains how to implement, update, and reset
Error Boundaries in modern React applications, covering both traditional
class-based implementations and the modern, hook-compatible
react-error-boundary library.
Understanding the Classic Error Boundary
Historically, React requires class components to define Error
Boundaries, as the hook equivalents for
getDerivedStateFromError and componentDidCatch
do not yet exist.
An Error Boundary updates its state when an error is thrown using the
static method getDerivedStateFromError().
import React, { Component } from 'react';
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true, error };
}
componentDidCatch(error, errorInfo) {
// You can also log the error to an error reporting service
console.error("Logging error:", error, errorInfo);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return (
<div>
<h2>Something went wrong.</h2>
<p>{this.state.error?.message}</p>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundary;How to Update and Reset the Error State
A common requirement is updating the Error Boundary so users can “try again” or recover from the error without refreshing the entire browser tab.
To update the error state back to normal, you must implement a reset mechanism within the class component.
class RecoverableErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError() {
return { hasError: true };
}
handleReset = () => {
// Reset the error state to allow re-rendering of children
this.setState({ hasError: false });
};
render() {
if (this.state.hasError) {
return (
<div>
<h2>An error occurred.</h2>
<button onClick={this.handleReset}>Try Again</button>
</div>
);
}
return this.props.children;
}
}Updating to Modern Functional React
To update your codebase to use functional components and React Hooks,
you should use the industry-standard react-error-boundary
library. This wrapper library allows you to manage and update error
states without writing class components.
First, install the package:
npm install react-error-boundaryImplementing
ErrorBoundary with Fallback and Reset
The ErrorBoundary component from this library accepts a
FallbackComponent and an onReset prop, making
it easy to update the component state when a user attempts to
recover.
import { ErrorBoundary } from 'react-error-boundary';
function ErrorFallback({ error, resetErrorBoundary }) {
return (
<div role="alert">
<p>Something went wrong:</p>
<pre>{error.message}</pre>
<button onClick={resetErrorBoundary}>Try again</button>
</div>
);
}
function App() {
return (
<ErrorBoundary
FallbackComponent={ErrorFallback}
onReset={() => {
// Reset the state of your app here so the error doesn't happen again
console.log("App state reset successfully");
}}
>
<MyBuggyComponent />
</ErrorBoundary>
);
}Updating State Automatically on Navigation
You can also update the error boundary state automatically when
specific values change (like a route change or a state variable change)
using the resetKeys prop.
import { useState } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
function App() {
const [someState, setSomeState] = useState("initial");
return (
<ErrorBoundary
FallbackComponent={ErrorFallback}
// When 'someState' changes, the Error Boundary automatically resets
resetKeys={[someState]}
>
<MyBuggyComponent stateValue={someState} />
</ErrorBoundary>
);
}