reactjsreact-routerreact-router-dom

React Router - How can I reuse my layout for the errorElement in the root route?


I'm using React Router v6 and following are my routes:

const router = createBrowserRouter([
  {
    path: '/',
    element: <App />,
    errorElement: <ErrorPage />,
    children: [
      {
        index: true,
        element: <HomePage />,
      },
      {
        path: '/sign-up',
        element: <SignUpPage />,
      },
      {
        path: '/log-in',
        element: <LogInPage />,
      },
    ],
  },
]);

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement,
);

root.render(
  <React.StrictMode>
    <RouterProvider router={router} />
  </React.StrictMode>,
);

The App component contains my app's layout and outputs the route elements using the Outlet component. But now if there's an error that bubbles up to the root route, then the ErrorPage gets displayed as expected, but it doesn't make use of the layout from App... So, how can I reuse my layout from App when the error page gets displayed?


Solution

  • When there's an error it is kind of an either/or kind of scenario. Either the conditions are fine, and the App component is rendered or there's an error condition, and the ErrorPage component is rendered.

    What you could do is abstract the layout portion of the App component into a layout component on its own that can render either a passed children prop or the Outlet component for the nested route, and render it in App and also wrap the ErrorPage component.

    Example:

    const AppLayout = ({ children }) => (
      ...
      {children ?? <Outlet />}
      ...
    );
    
    const App = () => (
      ...
      <AppLayout />
      ...
    );
    
    const router = createBrowserRouter([
      {
        path: "/",
        element: <App />, // <-- uses Outlet
        errorElement: (
          <AppLayout>     // <-- uses children
            <ErrorPage />
          </AppLayout>
        ),
        children: [
          {
            index: true,
            element: <HomePage />
          },
          {
            path: "/sign-up",
            element: <SignUpPage />
          },
          {
            path: "/log-in",
            element: <LogInPage />
          }
        ]
      }
    ]);
    

    Edit react-router-how-can-i-reuse-my-layout-for-the-errorelement-in-the-root-route