So far, we’ve been able to capture errors, log them to the console, and show a fallback UI. This makes it possible for the rest of our application to continue running - but how do we recover the broken component beyond refreshing the page?
Our <ErrorBoundary>
component determines whether to render the child component or the fallback UI based on its own internal this.state.error
value. If we change this error
state value back to null
, the ErrorBoundary
component will re-render along with the child component wrapped by the error boundary.
While there are many ways to do this, in this exercise we’ll walk through one fairly basic approach — adding a button that the user can press to reset the broken component. Take a look at the example below:
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { error: null }; this.reset = this.reset.bind(this); } reset() { this.setState({ error: null }); } static getDerivedStateFromError() { //... } componentDidCatch() { //... } render() { if (this.state.error) { return ( <div> <h2>Something went wrong.</h2> <button onClick={this.reset}> Reset </button> </div> ); } return this.props.children; } }
In this example, we:
- Modified the
constructor()
function to bind thereset()
method to the class component’sthis
value. This step is necessary to ensure that thethis.setState()
call withinreset()
has the properthis
reference. You can read more about why this is necessary in the React docs. - Created a new event handler function,
reset()
. When called, it will set theerror
state value tonull
. - Created a new button element in the fallback UI with
this.reset
assigned to theonClick
prop.
When the user clicks on the button element in the fallback UI, the reset()
function will be called and the error
state value will be reset to null
. As a result, the ErrorBoundary
component will re-render and will render this.props.children
.
In production applications, the reset()
logic may be more involved. We may attempt to recover unsaved data, make an API call to reset state on a server or database, or log out a user to avoid undesired access to protected features. This example paints a high-level picture of what needs to be done to get our application back to a running state.
Let’s try it out ourselves!
Instructions
First, we need to reset the internal state value of our error boundary so that we can get back to rendering the error boundary’s children. To do this:
- Define a function called
reset()
that set theerror
state value to benull
. - In the
constructor()
method, properly bindthis.reset
.
Next, we need to give the user a way to trigger this reset:
- Below the
<h2>
in your fallback UI, add a<button>
component - Add an
onClick()
prop to the<button>
whose value is yourthis.reset
function. - The text shown on the button may be anything you choose!
Test that your code works by pressing one of the first three broken buttons. You should now see the reset button! Try pressing the reset button and see your components re-render!
You should even be able to have multiple components showing their error boundaries at the same time. You can reset them in any order!
Note: The fourth button should still break with no reset option since it doesn’t have an error boundary.