In the ground since Fri Oct 01 2021
Last watered inFri Oct 01 2021
These are the most common types of errors that can occur in a React application:
Let's start by understanding how to handle them.
By default, if out application throws an error during rendering or effects, did-mount/did-update. React will remove its UI from the screen. The <body> tag will be almost empty. Our UI gets removed!

These are errors that occur when we:



To prevent this, we can use an approach called "Error Boundary".
An error boundary is a special component that lets you display some fallback UI instead of the part that crashed—for example, an error message.
Currently, the official doc only points to solution using React Class Components. To use a function component Error Boundary, we can use ErrorBoundary or useErrorBoundary hook from react-error-boundary library.
It focus on wrapping the components that might throw an error. If it happens, the error is caught by the nearest error boundary. The error boundary will then display a fallback UI.
Before continuing, if anything does't work as expected, we need to remember that some situations are not covered by error boundaries:
These cases will be covered in the next sections. But furst, let's ignore them!
We'll create an Fallback UI to informe the user about the error. We'll wrap ComponentThatWillBreak with ErrorBoundary.


Way Better! But...
Real world applications are complex and grow fast. They will have nested Components. ErrorBoundary will look for errors in a Parent Component. If everything's fine, it will keep going down the tree to check if nested/children Components are throwing errors.
Now the app have two errors:
| ComponentThatWillBreak -> "user.address is undefined" | - MyChildComponent -> "user.lastLogin is undefined"
ErrorBoundary will catch the first error only and display it. Only that.
If we fix the first error, the second one will be displayed.

Nice! It's safe to assume that we can create a "Global" Error Boundary and place it at the Top Level of our App. Fallback a generic message to all possible errors that might happen.
It's not perfect, but at least our App doesn't show an Empty screen and we can in the future use the FallbackComponent to log the error and send it to a monitoring tool.
We can definetly have one ErrorBoundary nested for the whole App. But we can also have multiple ErrorBoundary for specific Components. It's up to us to decide which one to use. It's a matter of context and complexity of the App
Let's create an approach:
Mental Model
Level 1 It's a global treatment. If in the future, any Component is added in the App and it's not wrapped in a Error Boundary, we can rest assured that if it breaks, we'll know and we'll display a properly Fallback UI. A Generic one? 100%. But still better tha n a blank page!
Level 2 It's a more specific treatment. We can wrap a specific Component that we know that might break. We can display a more specific Fallback UI. We can even grab the error and treat it.
Now it's time to use them:
When an error is caught by the GlobalFallback:

When an error is caught by the ChildFallback:

Cool! But writting two Components SomethingFallback SomethingFallbackUI to all Components of a complex App will add complexity to the code.
We can use Higher Order Components to wrap the Components that might break. A HOC is a function that takes a Component, alter the given Component, in any matter and returns a new Component. We can use it to wrap the Components that might break.
We can forçe a re-render after an error. It make sense if we're dealing with a fetch that failed or if we have a strategy where we would fix the cause of the error.
We have two options. By calling a hook useErrorBoundary or by using a prop onReset in the ErrorBoundary component.
Calling the hook inside the Component which we want to recover for
Calling onReset
In real-world App we might want to store all errors using a monitoring tool. We can use the onError prop in the ErrorBoundary component to log the error.
-> Write an error on event handlers. A click will do! -> Write an Error simulating a fetch that fails
https://react.dev/reference/react-dom/client/createRoot#displaying-error-boundary-errors
https://react.dev/reference/react-dom/client/createRoot#displaying-a-dialog-for-recoverable-errors