-
Notifications
You must be signed in to change notification settings - Fork 143
Error boundaries! #173
base: master
Are you sure you want to change the base?
Error boundaries! #173
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good! I appreciate the thorough tests.
I think it's probably fine to allow returning a stateUpdater, mostly because it should make it easier to respond to errors intelligently. Just getting the error message doesn't help much if you want to branch on different kinds of errors because it backs you into doing string matching. Maybe being able to optionally see the props/state helps component authors respond more intelligently?
That said, the typical pattern is to create dedicated ErrorBoundary components that know what to do with errors, so that component's own props/state may or may not be of much value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops, realized I'd started this comment but conversed about it offline before posting it. Leaving the comment so it's clear why we haven't come back to this change yet.
else | ||
reconciler.updateVirtualNodeWithRenderResult(virtualNode, hostParent, renderResult) | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It just occurred to me that this implementation doesn't actually catch errors if they occur downstream of this call site.
For example, suppose I have:
ComponentA
|--ErrorBound
|----ComponentB
Consider these scenarios:
ComponentA
renders, causingComponentB
to render.ComponentB
throws an error. TheErrorBound
catches and handles it just fine.- After all of this is mounted,
ComponentB
has a state update triggered, and re-renders.ComponentB
throws an error. TheErrorBound
won't be involved in reconciling it, so it won't be invoked!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I need to revisit this when I have the time - there are definitely cases that error boundaries should catch, but don't.
Adds error boundaries like React's newer version of them. An error boundary is any component that declares a method with the signature
static getDerivedStateFromError(message: string) -> setStateMapper
. If this method is declared, the component will capture any errors from its children, pass the message togetDerivedStateFromError
, apply the resulting state delta, then re-try the render.The boundary will re-try the render only once; if the re-tried render throws, that error will propagate upwards until it either surfaces or hits another error boundary. It is the responsibility of the error boundary component to make sure this doesn't happen. If the re-render succeeds, the normal lifecycle process (calling either
didMount
ordidUpdate
depending on which is appropriate) will continue.Questions I'm not sure about:
getDerivedStateFromError
be allowed to return a mapper function, or should it only be allowed to return a dictionary? Allowing a function to be returned gives the function, indirectly, access to the component's state and props tables.Checklist before submitting: