Use react's context to display an error message somewhere else
Honestly, the end result seems so trivial that I almost couldn’t be bothered to write it up. Then again, it shouldn’t take too much time to write it down. 🤷
The problem
react components allow you to deal with all aspects of some interaction with the user. But maybe you want some parts of the interaction to visually appear somewhere else?
Example: A form has a component that renders a delete button and also takes care of triggering the actual deletion. However, in case of an error you want the error to display in the error area of the whole form.
A solution
Let’s have some functionality dedicated to allowing components to render an error to some other place. For this we define a react context and a component that makes it simple to use that context:
the context allows to change the error. In order to propagate rerenders every time that this component renders, we memoize the context. The setError
callback remains stable throughout the lifetime of the component, hence we only check whether error
changes.
Next comes a component which is used to show the error in the place where you want it.
If the error context provides an error, it will be rendered. How do we communicate errors to the context? You can think of one of two ways.
Component with error prop
This component doesn’t ever render anything. However, you can pass it an error property and will then communicate the error to the context. Just notice however that the error property is not necessarily in sync with the error stored in the error context. This should be a good thing, since the component will simply not overwrite any error in the context as long as it’s not rerendered.
Also note the use of useRef
- the ErrorInlet
has exactly 2 reasons why it could be rendering:
- Either by the parent component rendering it, or
- by the error context changing.
With the useRef
we can track the context in use and hence decide whether the error inlet is being rendered - in which case the error passed in will be set.
Look e.g. at this component:
Note that if someError
is null and you’d try to overwrite by setting to null, react notices that the state is already null and won’t rerender anything!
using “useErrorOutlet” hook
This hook is implemented as follows:
And can be used e.g. like this:
setError
may also be used in an effect when the error appears as a value relevant for rendering.
Finally, an App using this would look something like this: