Skip to content

ErrorBoundary with an Outlet component re-render the current route before the next route #2318

Open

Description

@Ganbin

Which project does this relate to?

Router

Describe the bug

Situation

I use a pathless route and the layout is used in order to have a generic ErrorBoundary to catch any error, display the error and show a retry button.

If an error occurs and we try to navigate to another route, the erroneous component (of the current route) will re-render before the new route. This can cause some re-fetch to occurs if the component error was due to some fetching error (which is usually the case). This slow down the application and can lead to some unexpected side-effect.

Your Example Website or App

https://stackblitz.com/edit/github-dgnsgk?file=src%2Froutes%2F_app.tsx

Steps to Reproduce the Bug or Issue

  1. Open the console
  2. Go to the Posts route. An error will be displayed.
  3. Navigate to any other route.

Expected behavior

The Posts component should not be re-render before rendering the new route.

Screenshots or Videos

2024-09-11_15-39-28.mp4

Platform

  • OS: macOS (only tried on macOS but it is surely the same on Windows)
  • Browser: Brave, Chrome, Safari, Firefox
  • Version: 1.57.9

Additional context

ErrorBoundary and resetKey

From what I see, the resetKey of the ErrorBoundary which is set to [location.pathname] from Tanstack Router useLocation resets before the <Outlet /> render the new route.

So the sequence can look like :

  1. Click on Link component to navigate to a new route
  2. location.pathname change, thus it will reset the ErrorBoundary and the current component displayed in Outlet component
  3. Outlet component render the new route

I'm not really sure if this is an issue on Tanstack Router or if this is a general issue on how ErrorBoundary component works. But I feel like the location should be in sync with the Outlet Component in the render cycle.

React Router

I first thought it was a react query issue, I have searched in every repo (react-query and react-router) to find about the issue but could only find something related to the Errored queries caught by ErrorBoundary are not retried on mount (TanStack/query#271) and first posted a comment there TanStack/query#2712 (comment).

Solution

The current solution is to wrap every route inside a custom ErrorBoundary component but this remove the utility of a pathless route and the use of a layout which was a good fit for this use case.
My example use a pathless route with a layout component but the issue could surely be reproduced with a normal route that wrap the Outlet component inside an ErrorBoundary

Activity

  1. agronbajraktari commented on Sep 18, 2024

    @agronbajraktari

    I have the same issue!

  2. agronbajraktari commented on Sep 18, 2024

    @agronbajraktari

    Never mind, had to simply update the lib.

  3. alex-delia commented on Dec 21, 2024

    @alex-delia
    Contributor

    Try creating an error component instead of wrapping the whole component in an error boundary.

    https://tanstack.com/router/latest/docs/framework/react/guide/external-data-loading#error-handling-with-tanstack-query

    errorComponent: ({ error, reset }) => {
        const router = useRouter()
        const queryErrorResetBoundary = useQueryErrorResetBoundary()
    
        React.useEffect(() => {
          // Reset the query error boundary
          queryErrorResetBoundary.reset()
        }, [queryErrorResetBoundary])
    
        return (
          <div>
            {error.message}
            <button
              onClick={() => {
                // Invalidate the route to reload the loader, and reset any router error boundaries
                router.invalidate()
              }}
            >
              retry
            </button>
          </div>
        )
      },
    

    It seems to work this way

    https://stackblitz.com/edit/github-dgnsgk-7kjfacg2?file=src%2Froutes%2F_app.tsx

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions