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?
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 />
}
]
}
]);