Replies: 1 comment
-
Here's an attempt at an error boundary whose key only changes after an error has occurred (i.e. not on every URL change): https://gist.github.com/donaldpipowitch/1248ca4658506c7c8b481edfbd740ca7 |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Take this minimal app with lazy-loading per route:
The
ErrorBoundary
component is a class-based error boundary, keeping some boolean flag state that's turned on when there was an error. This includes lazy-loading errors (i.e. the chunk fetch failed).The problem is that the way reconciliation works, the error boundary will be shared across all sibling routes inside a certain parent
Routes
. So the inner state of this ever-lasting error boundary is not reset when you switch to other views.My first instinct, trying to be clever, was to put a single error boundary around it all, and have it use the
useLocation().key
as itskey
prop. That way, you'd get a new error boundary every time you switch views. However, this soon proves being an issue. This makes your app re-mount views that should not be unmounted and mounted again. For instance, a mere change in the query params of a view re-mounts the entire view. Switching to theuseLocation().pathname
instead of thekey
might improve that particular scenario, but it still re-mounts onpathname
changes that are not really switching to another view.So the only remaining alternative I see is manually applying a key per error boundary:
This, however, becomes repetitive and verbose pretty soon. Not to mention error-prone. So the next step would be to make a helper to reuse this pattern.
You'd think you could make a
MyAppRoute
sort of component wrapping theRoute
component, but that's a no-go. TheRoutes
component requires that its children must be exclusivelyRoute
elements (ref). So your only choice is to move away from jsx and create a helper function that is not meant to be called as a React component, but directly instead:Which you would use like this:
Much better for this simpler example. But it still can become inconvenient or unidiomatic when your
Route
elements also requirechildren
.So the question is: is this the only way? Or am I missing something and there's a better way to make this work while keeping the ergonomics and the idiomatic use of React and JSX more intact than the direction on which I'm going?
Beta Was this translation helpful? Give feedback.
All reactions