-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(react): Add Sentry.reactErrorHandler
#12147
Conversation
3cdc306
to
7741886
Compare
size-limit report 📦
|
packages/react/README.md
Outdated
const root = createRoot(container, { | ||
// Callback called when an error is thrown and not caught by an Error Boundary. | ||
onUncaughtError: (error, errorInfo) => { | ||
Sentry.captureReactException(error, errorInfo); |
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.
I would vote for a different name here - imho this is a bit misleading, like I could easily see users just using this instead of captureException()
🤔
What if instead we'd do something like this:
const root = createRoot(container, {
// Callback called when an error is thrown and not caught by an Error Boundary.
onUncaughtError: Sentry.reactErrorHandler(),
onCaughtError: Sentry.reactErrorHandler((error, errorInfo) => {
// optional callback if users want more/custom config in addition?
})
});
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.
I like Sentry.reactErrorHandler
a lot better - will change!
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.
I have some concerns with my initial approach that also applies to Sentry.reactErrorHandler
. #11798 (comment)
Pinged react team member on this, let's see if we can get feedback.
packages/react/src/error.ts
Outdated
* Recurse through `error.cause` chain to set cause on an error. | ||
*/ | ||
export function setCause(error: Error & { cause?: Error }, cause: Error): void { | ||
const seenErrors = new WeakMap<Error, boolean>(); |
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.
l: could use a WeakSet
here instead, wdyt?
Sentry.reactErrorHandler
cf24410
to
2550dac
Compare
0ba4bcd
to
c306b49
Compare
15d3d2d
to
9224b63
Compare
ref #11798
React 19 brings some improvements to error handling with https://react.dev/blog/2024/04/25/react-19#error-handling! This PR exposes a new method,
Sentry.reactErrorHandler
that helps users interact with these new React 19 error handling hooks.Background
React Error handling originally relied only on error boundaries, React components that would automatically catch component rendering errors and display fallback UIs.
We added support for this by exporting our own
ErrorBoundary
component.If you notice above, the
info
parameter passed intocomponentDidCatch
has acomponentStack
property.componentStack
is a synthetic stacktrace that represents the component call-chain that threw the error. Fortunately because this is a synthetic stacktrace, we can parse it as an error in the SDK and attach it to the original exception as a linked exception viaerror.cause
.Important to note: If a component chain is not wrapped in an error boundary though, we do not get access to the
componentStack
, as the error bubbles up to the global error handler.React 19
In React 19 they've two new options,
onCaughtError
andonUncaughtError
to the React DOM public API.onCaughtError
is a callback called when React catches an error in an Error Boundary. This effectively works just like having anErrorBoundary
withcomponentDidCatch
.onUncaughtError
is a callback called when an error is thrown and not caught by an Error Boundary. This means we can addcomponentStack
information to these errors without requiring users to add error boundaries everywhere (useful for 3rd party component libraries and similar).Given
onCaughtError
,onUncaughtError
andcomponentDidCatch
all have identical APIsThis PR introduces
Sentry.reactErrorHandler
, which looks like so:To validate this change, we add a react 19 e2e test.
Next Steps
After we merge this in and update the docs, we can explore automatically instrumenting
createRoot
fromreact-dom
to addSentry.reactErrorHandler
accordingly, but that is a next step.