Optimizing React Components with Error Boundaries
Disclaimer: The concept discussed in this article is part of the advanced concepts of React as outlined in the official docs. But I see it as something every react developer should know and use. You would find this my view to be accurate at the end of this tutorial.
By its original design, when JavaScript errors occur in a component as little as a Button
component, it leads to the complete crash and failure of the react application. At the time react did not provide a way to handle this, neither was it able to recover from these errors when they occurred.
But now, the React team at facebook with the advent of React 16, introduced a new concept for error handling called error boundaries
.
Introducing Error Boundaries:
With the introduction of error boundaries
, components can have errors and crash in peace without having to affect the entire application state causing an application-wide crash
According to the React Documentation,
Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. Error boundaries catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them.
Error boundaries work like the catch(){}
block in JavaScript, but this time for components. Someone could say since it works like JavaScripts catch(){}
block, why don't we use try/catch
of creating error boundaries. So we could have something like this:
try {
<ShowButton />
} catch(err) {
console.log(err)
}
This looks good and could solve the problem we want to solve with Error Boundaries
, but the thing is try/catch
only works for imperative code, but since we are working with react, which is declarative, react components are declarative and specify what should be rendered. But with Error Boundaries
the declarative nature of React is preserved.
Just to add to this article, to understand the difference between imperative code and declarative code, look at these articles, here and
here
Error Boundaries, can only be class components, how do I mean, you can't use functional components, to create an error boundary
, but a class component.
For a class component to be considered an error boundary, it needs to have either (or both) of the lifecycle methods static getDerivedStateFromError()
or componentDidCatch()
. Where getDerivedStateFromError()
is used to render a fallback UI with the error response the developer specifies, and componentDidCatch()
is used to log error information, so here you could be using any log service of your choosing, or our favorite console.log
.
To jump into code, this is what an error boundary looks like;
import React, {Component} from 'react';
class ErrorBoundary extends 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, info) {
// You can also log the error to an error reporting service
logErrorToMyService(error, info);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
The code example was extracted from the react documentation, and for further reads, I would suggest you likely have a look at it.
With Error boundaries
in place in our code, we won't have a mere error in our button component render, kill the entire application, we would have complete control over such things, and the users of the application won't be left wondering what happened.
To use the created error boundary
, all we have to do is, wrap any component we want to be covered by error boundary within it as so;
Lastly, it's important to note that, error boundaries can't be used within event listeners. When dealing with event listeners, it's best to use the try/catch
block.
Note: How you want to use
error boundaries
, is totally up to you, you could have your entire application wrapped in an error boundary or simply have individual components wrapped within an error boundary. But, it is still highly recommended that you just put your in a few strategic places.
For further reads on error boundaries, I won't recommend other sources than the react documentation here
I hope you enjoy using error boundaries
as I do. That's it from me here, if you have any questions or feedback feel free to comment or DM on twitter
Thank you for highlighting this concept for beginners like myself.
I’m glad you enjoyed it