visit
Because of the importance of handling errors we stated above, it is very important to handle potential issues that may happen, and eventually provide suitable feedback to the users and also to the developers so that those errors are quickly fixed.
The component stack trace additionally includes filenames and line numbers that you can use to see where exactly the error happened. The component stack trace works by default in projects created using . If you don’t use it, you can manually add to your Babel setup.
If you are familiar with JavaScript, you are probably familiar with the usual try … catch
block used to catch errors.
Using the usual try...catch
statement is not effective to catch errors in your react components because it only works for imperative code and not the declarative code we write in JSX.
Moreover, with a try...catch
statement, we might cause the entire react app to break instead of just the faulty component which is not what you most probably want.
setTimeout
or requestAnimationFrame
callbacks)
Error Boundaries are implemented using class components. According to the , a class component becomes an error boundary if it defines either (or both) one of the lifecycle methods static getDerivedStateFromError
or componentDidCatch
.
static getDerivedStateFromError(error)
is used to render a visual fallback UI after an error has been thrown. It will be called after a descendant component throws an error. This method takes the error as an argument and the value returned by this function is used to update the state.
componentDidCatch(error, info)
is usually used to log error information. It will be called as soon as an error reaches our component. This method accepts two arguments:
error
- The error that was throwninfo
- An object storing the componentStack trace showing which component has thrown this error.As we previously mentioned, an error boundary is just a class component that implements one of those methods static getDerivedStateFromError()
or componentDidCatch()
or both.
import { Users } from "./Users";
function App() {
return (
<div className="App">
<h1>Hello dear reader</h1>
<Users />
</div>
);
}
export default App;
export const Users = () => {
throw new Error("Error!");
return <div> Users </div>;
};
To prevent the app from entirely crashing, we need to add the Error Boundary component. Here is a simple implementation of an error boundary class
import React from "react";
export class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
console.error(error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
import { ErrorBoundary } from "./ErrorBoundary";
function App() {
return (
<div className="App">
<h1>Hello</h1>
<ErrorBoundary>
<Users />
<ErrorBoundary />
</div>
);
}
export default App;
If you are not satisfied with the features offered by the Error Boundary component, you can use the react-boundary-library
that provides a retry mechanism as well as a way to render a fallback component in case of an error.
# if you use npm
npm install --save react-boundary-library
# if you use yarn
yarn add react-boundary-library
To handle errors using this library, you can do it simply by wrapping the component where your error might show up inside the ErrorBoundary
component from react-boundary-library
. You can also provide a fallback component as a prop to the Error Boundary component which will be the UI shown in case of an error. Here is a concrete example
import { ErrorBoundary } from "react-error-boundary";
import { Users } from "./Users";
function ErrorFallback({ error, resetErrorBoundary }) {
return (
<div role="alert">
<p>Failed to load users:</p>
<p>{error.message}</p>
<button onClick={resetErrorBoundary}>Try again</button>
</div>
);
}
function App() {
return (
<div className="App">
<h1>Hello dear reader</h1>
<ErrorBoundary FallbackComponent={ErrorFallback}>
<Users />
</ErrorBoundary>
</div>
);
}
The fallback component accepts error
and resetErrorBoundary
as props. The resetErrorBoundary
prop will reset the error boundary's state when called, and can be useful for a "try again" button. error
is the thrown error.
In the case of web applications and more specifically in the case of web components, modern JavaScript frameworks usually offer ways to handle errors that might be in your web component other than just the usual try … catch
. Error Boundaries components are an effective solution offered in the React ecosystem for that purpose. This solution helps in offering visual UI feedback and stops the error propagation in order to not cause the entire app to crash. There are as well other libraries that one can use to provide an advanced error-handling experience such as react-boundary-library
in the React ecosystem.
If this post was helpful to you in any way, please don't hesitate to share it. You can also follow if you would like to see more content related to web programming.