Editor’s note: This article was updated on 13 April 2022 to reflect the most recent information for react-error-boundary, including use of the withErrorBoundary
function as a higher order component.
Errors are bound to happen in our applications, whether they’re server-related errors, edge cases, or others. As such, many methods have been developed to prevent these errors from interfering with user and developer experience. In React, one such method is the use of error boundaries.
In this article, we’ll examine React error handling using react-error-boundary. We’ll cover the following:
Error boundaries in React
Error boundaries were introduced in React 16 as a way to catch and handle JavaScript errors that occur in the UI parts of our component. So error boundaries only catch errors that occur in a lifecycle method, render method, and inside Hooks like useEffect
. According to the React documentation, error boundaries do not handle errors in:
- Event handlers
- Asynchronous code (e.g.,
setTimeout
orrequestAnimationFrame
callbacks) - Server-side rendering
- Errors thrown in the error boundary itself (rather than its children)
So basically, error boundaries only handle errors in the parts of our code that involve React.
To create an error boundary, we simply have to create a class component and define a state variable for determining whether the error boundary has caught an error. Our class component should also have at least three methods:
- A static method called
getDerivedStateFromError
, which is used to update the error boundary’s state - A
componentDidCatch
lifecycle method for performing operations when our error boundaries catch an error, such as logging to an error logging service - A
render
method for rendering our error boundary’s child or the fallback UI in case of an error
Here’s an example (taken from the React docs) of what our simple error boundary should look like:
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { // Update state so the next render will show the fallback UI. return { hasError: true }; } componentDidCatch(error, errorInfo) { // You can also log the error to an error reporting service logErrorToMyService(error, errorInfo); } render() { if (this.state.hasError) { // You can render any custom fallback UI return <h1>Something went wrong.</h1>; } return this.props.children; } }
react-error-boundary
react-error-boundary is a wrapper around React’s error boundary that allows developers to implement error boundaries in code without building them from scratch. With react-error-boundary, we can simply wrap components where we expect errors with the provided ErrorBoundary
component and pass in some extra props to customize our error boundary’s behavior.
In this article, I will work through using react-error-boundary to deal with errors in a React application. Let’s take a look at what the library offers.
ErrorBoundary
component
The ErrorBoundary
component is the main component available in react-error-boundary. It allows us to implement the typical React error boundary with less code.
Here’s a very basic use case of ErrorBoundary
:
function App(){ ... return ( <ErrorBoundary FallbackComponent={OurFallbackComponent} > <ComponentThatMightThrowAnError/> </ErrorBoundary> ); } const OurFallbackComponent = ({ error, componentStack, resetErrorBoundary }) => { return ( <div> <h1>An error occurred: {error.message}</h1> <button onClick={resetErrorBoundary}>Try again</button> </div> ); };
In the above component, we simply wrap our component with the ErrorBoundary
component and pass in our fallback component to the FallbackComponent
prop so that if there’s an error (that can be caught and handled by react-error-boundary), our fallback component will be rendered; otherwise, our component will be rendered.
We also have the fallbackRender
prop, which is a render prop-based API for specifying our fallback component in an inline manner. Here’s the above code block using the fallbackRender
prop:
function App(){ ... return ( <ErrorBoundary fallbackRender = {({error, resetErrorBoundary, componentStack}) => ( <div> <h1>An error occurred: {error.message}</h1> <button onClick={resetErrorBoundary}>Try again</button> </div> )} > <ComponentThatMightThrowAnError/> </ErrorBoundary> ); }
The ErrorBoundary
also has an onError
prop, which acts as a listener that is triggered when our error boundary catches and handles an error in its child components. It is from this place that we might choose to log such errors to whatever error logging service we might be using.
function App(){ ... return ( <ErrorBoundary onError = {(error, componentStack) => { logToErrorLoggingService(error, componentStack); }} ... > <ComponentThatMightThrowAnError/> </ErrorBoundary> ); }
Resetting error boundaries
react-error-boundary also provides a way for our code to recover from errors caught by our error boundaries. This is done using the reset keys and the resetErrorBoundary
function passed to the fallback component.
The best way to explain how this works is to use an example code block taken directly from the React documentation:
function ErrorFallback({error, componentStack, resetErrorBoundary}) { return ( <div role="alert"> <p>Something went wrong:</p> <pre>{error.message}</pre> <pre>{componentStack}</pre> <button onClick={resetErrorBoundary}>Try again</button> </div> ) } function Bomb() { throw new Error('💥 KABOOM 💥') } function App() { const [explode, setExplode] = React.useState(false) return ( <div> <button onClick={() => setExplode(e => !e)}>toggle explode</button> <ErrorBoundary FallbackComponent={ErrorFallback} onReset={() => setExplode(false)} resetKeys={[explode]} > {explode ? <Bomb /> : null} </ErrorBoundary> </div> ) }
As we can see from the code above, a state Hook was created and used to determine whether the App
component renders a Bomb
component that throws an error or an error-safe component. Reset keys were also passed to the error boundary component. These reset keys determine whether the error boundary’s internal state will be reset. If one of the reset keys change during renders, the error boundary’s internal state will be reset.
On the other hand, calling the resetComponent
function triggers the onReset
handler of our ErrorBoundary
component, where we set our explode
state value to false
. This causes our App
component to render an error-safe component.
We also have the onResetKeysChange
handler, which is triggered when the value of the reset keys change, causing a reset of the error boundary’s internal state.
useErrorHandler
Hook
Another great feature of the react-error-boundary library is that it allows developers to use error boundaries to catch errors that wouldn’t otherwise be caught by traditional React error boundaries. This means we can now use error boundaries to catch errors during API requests, event handlers, and other parts of code where errors could occur.
There are two ways to use the useErrorHandler
Hook:
const handleError = useErrorHandler()
: then we can call thehandleError(error)
and pass in the error object, just like in the example belowuseErrorHandler(error)
: this is useful when we’re handling the error state ourselves or when we’re getting it from another Hook
This is how we would catch errors in an API request using the first method:
const App = () => { return ( <ErrorBoundary FallbackComponent={CharacterFallback} > <ComponentWhereErrorMightOccur/> </ErrorBoundary> ); }; const ComponentWhereErrorMightOccur = () => { const handleError = useErrorHandler(); const callAPI = () => { const result = fetch(apiURL) .then( (response) => response.json(), (error) => handleError(error)) .then((data) => { return data["results"]; }); return result; }; useEffect(() => { (async function () { await callAPI(); })(); }, []); return ( ... ); };
As you can see, all we need to do is pass the error object returned from fetching data from our API to our handleError
function, which was returned by the useErrorHandle
Hook. This way, our error boundaries are more useful.
withErrorBoundary
function as HOC
React-error-boundary allows us to utilize the withErrorBoundary
function as a higher order component (HOC) to manage problems within components. This way we can focus on developing components while leaving error handling to the function. Furthermore, this method decreases the amount of code required to implement the component and its tests.
Here’s an example from the react-error-boundary docs for how to use this:
import {withErrorBoundary} from 'react-error-boundary' const ComponentWithErrorBoundary = withErrorBoundary(ComponentThatMayError, { FallbackComponent: ErrorBoundaryFallbackComponent, onError(error, info) { // Do something with the error // E.g. log to an error logging client here }, }) const ui = <ComponentWithErrorBoundary />
Conclusion
react-error-boundary enables React developers to reduce the amount of code that must be written and expand their error boundary capabilities to catch other forms of errors that wouldn’t otherwise be identified by regular error boundaries. Learn more about react-error-boundary on GitHub.
Cut through the noise of traditional React error reporting with LogRocket
LogRocket is a React analytics solution that shields you from the hundreds of false-positive errors alerts to just a few truly important items. LogRocket tells you the most impactful bugs and UX issues actually impacting users in your React applications.

Focus on the React bugs that matter — try LogRocket today.
Have you tried react-badly? Same idea as a wrapper around react error boundary