Skip to content

feat(react-router): add unstable_onError prop to RouterProvider for client side error reporting #14162

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

Merged
merged 13 commits into from
Aug 20, 2025

Conversation

brophdawg11
Copy link
Contributor

@brophdawg11 brophdawg11 commented Aug 12, 2025

Implements: #12958
RFC: #9881

API:

// Framework mode
<HydratedRouter unstable_onError={(error, errorInfo) => {
  console.log('Client error!", error, errorInfo);
}} />

// Data mode
<RouterProvider unstable_onError={(error, errorInfo) => {
  console.log('Client error!", error, errorInfo);
}} />

This is a client-side version of the entry.server handleError function to be used for client-side error reporting. This has 2 main advantages over the current approach of trying to log from ErrorBoundary:

  • It's decoupled from rendering so won't ever log duplicates on re-renders
  • It has access to the errorInfo prop from componentDidCatch for render errors

Copy link

changeset-bot bot commented Aug 12, 2025

🦋 Changeset detected

Latest commit: 3d7dcee

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
react-router Patch
@react-router/architect Patch
@react-router/cloudflare Patch
@react-router/dev Patch
react-router-dom Patch
@react-router/express Patch
@react-router/node Patch
@react-router/serve Patch
@react-router/fs-routes Patch
@react-router/remix-routes-option-adapter Patch
create-react-router Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@brophdawg11 brophdawg11 linked an issue Aug 12, 2025 that may be closed by this pull request
Comment on lines 343 to 358
let logErrorsAndSetState = React.useCallback(
(newState: RouterState) => {
setStateImpl((prevState) => {
// Send loader/action errors through handleError
if (newState.errors && unstable_handleError) {
Object.entries(newState.errors).forEach(([routeId, error]) => {
if (prevState.errors?.[routeId] !== error) {
unstable_handleError(error);
}
});
}
return newState;
});
},
[unstable_handleError],
);
Copy link
Contributor Author

@brophdawg11 brophdawg11 Aug 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Log loader/action errors every time we set state which should keep this synced with "report errors that are surfaced in the UI". This switches to use the setState callback function too so it can compare to prior state.errors to avoid duplicate reporting of errors on subsequent state updates (like calling a fetcher from an error boundary).

componentDidCatch(error: any, errorInfo: React.ErrorInfo) {
if (this.props.unstable_handleError) {
// Log render errors
this.props.unstable_handleError(error, errorInfo);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Log <Await> render errors

Object.defineProperty(resolve, "_error", { get: () => error }),
(error: any) => {
// Log promise rejections
this.props.unstable_handleError?.(error);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Log <Await> promise rejections

);
componentDidCatch(error: any, errorInfo: React.ErrorInfo) {
if (this.props.unstable_handleError) {
this.props.unstable_handleError(error, errorInfo);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Log render errors

@brophdawg11 brophdawg11 added the alpha-release Used by maintainers to trigger a Stage 2 (alpha) release on a PR label Aug 12, 2025
Copy link
Contributor

Alpha release created: 0.0.0-experimental-2eb7164

⚠️ Note: This release was created from the HEAD of this branch so it may contain commits that have landed in dev but have not been released yet depending on when this branch was created. You can run the following command to see the commits that may not have been released yet:

git log --pretty=oneline [email protected]

@github-actions github-actions bot removed the alpha-release Used by maintainers to trigger a Stage 2 (alpha) release on a PR label Aug 12, 2025
@brophdawg11 brophdawg11 changed the title Implement RouterProvider unstable_handleError prop for client side error reporting Implement RouterProvider unstable_onError prop for client side error reporting Aug 13, 2025
@MichaelDeBoey MichaelDeBoey changed the title Implement RouterProvider unstable_onError prop for client side error reporting feat(react-router): add unstable_onError prop to RouterProvider for client side error reporting Aug 13, 2025
@brophdawg11 brophdawg11 added the alpha-release Used by maintainers to trigger a Stage 2 (alpha) release on a PR label Aug 15, 2025
Copy link
Contributor

Alpha release created: 0.0.0-experimental-3d7dcee

⚠️ Note: This release was created from the HEAD of this branch so it may contain commits that have landed in dev but have not been released yet depending on when this branch was created. You can run the following command to see the commits that may not have been released yet:

git log --pretty=oneline [email protected]

@github-actions github-actions bot removed the alpha-release Used by maintainers to trigger a Stage 2 (alpha) release on a PR label Aug 15, 2025
@brophdawg11 brophdawg11 merged commit e9a17ed into dev Aug 20, 2025
10 checks passed
@brophdawg11 brophdawg11 deleted the brophdawg11/client-handle-error branch August 20, 2025 14:25
Copy link
Contributor

🤖 Hello there,

We just published version 7.8.2-pre.0 which includes this pull request. If you'd like to take it for a test run please try it out and let us know what you think!

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

RouterProvider onError
3 participants