{ sung.codes }

by dance2die
Blog
← Go Back

Resetting Error Boundary Error State

Broken Post?Let me know

For bunpkg, I use a Wizard component to display a series of steps to generate UNPKG links.

When a request to Web API fails, an error is caught with an Error Boundary component and display an error message in ErrorBoundary.FallbackComponent (from react-error-boundary
, a simple but better implementation found on React documentation).

But the error boundary wasn't reset when a user moved onto a different step in the wizard.

I would like to share my failed attempt and the proper workaround to reset Error Boundary components.

But this can apply to your custom ErrorBoundary component.

😪 TL;DR

Update Error Boundary key props to let React reset the error state.

ℹ About Demo

The following demo has a component that randomly throws an error and the error boundary shows the error message caught.

Credit: the demo program is created by Brian Vaugn on CodeSandBox.

Error Boundary Reset Demo

🙅‍♂️ First attempt (bad workaround)

react-error-boundary provides only following props (leaving out children) and no way to clear the error caught.

  • FallbackComponent -  A component to display in case of error
  • onError - A callback triggered on error

Following is how ErrorBoundary.render is implemented.

render() {
const {children, FallbackComponent} = this.props;
const {error, info} = this.state;
if (error !== null) {
return (
<FallbackComponent
componentStack={
info ? info.componentStack : ''
}
error={error}
/>
);
}
return children;
}

View this gist on GitHub

FallbackComponent is displayed if an error exists.

So my first attempt was to create a reference (this.errorBoundary) and directly manipulate it as it is a 3rd party component.

Yes, stupid of me to even attempt to directly manipulate the state even without using setState...

class Wizard extends Component {
errorBoundary = React.createRef();
// redacted unrelevant code...
onStepClick = current => {
this.errorBoundary.current.state.error = null;
};
render() {
const { current } = this.state;
return (
<div>
<Steps current={current}>
{steps.map((item, step) => (
<Steps.Step
key={item.title}
onClick={e => this.onStepClick(step)}
/>
))}
</Steps>
<div className="steps-content">
<ErrorBoundary
ref={this.errorBoundary}
FallbackComponent={ErrorFallbackComponent}
>
{this.getContent()}
</ErrorBoundary>
</div>
</div>
);
}
}
view raw Wizard.js hosted with ❤ by GitHub

View this gist on GitHub

🙆 Proper Workaround

I knew that the workaround was just so hacky that I created a request ticket on react-error-boundary GitHub repository,  requesting to provide a way/prop to clear the error.

And Brian has replied with a proper React-way of resetting error boundary - provide a key to an instance of ErrorBoundary component to reset the instant.error in the next render phase.

View this gist on GitHub

class App extends React.Component {
state = {
errorBoundaryKey: 0
};
handleRerenderButtonClick = () => this.forceUpdate();
handleResetButtonClick = () =>
this.setState(prevState => ({
errorBoundaryKey: prevState.errorBoundaryKey + 1
}));
render() {
return (
<div className="App">
<button onClick={this.handleRerenderButtonClick}>re-render</button>
<button onClick={this.handleResetButtonClick}>
reset error boundary
</button>
<ErrorBoundary key={this.state.errorBoundaryKey}>
<ComponentThatMayError />
</ErrorBoundary>
</div>
);
}
}
view raw proper.js hosted with ❤ by GitHub

View this gist on GitHub

You can see that as you click on reset error boundary button, it updates the key on ErrorBoundary component (
<ErrorBoundary key={this.state.errorBoundaryKey}>) using handleResetButtonClick method, which will clear the internal error state by increasing errorBoundaryKey by one every time forcing a re-render.

😞 Failures

I was just too obsessed with "making things work" and overused Refs (even though ReactJS clearly recommends you not to).

Second of all, I didn't even consider using setState but directly manipulated the error state (this.errorBoundary.current.state.error = null).

👋 Parting Words

Many thanks to Brian for react-error-boundary, helping me realize the mistake and providing the workaround.

I hope the post help you should you run into the situation where an error boundary need to be reset & not go through the same bad practice/failures I mentioned above.

Lastly,  Bunpkg uses the workaround suggested.