In my application I am using BrowserRouter
component to render my routes or components, but I want to use loader
functionality. My current approach I am not able to use that feature.
<BrowserRouter>
<AppRoutes />
</BrowserRouter>
As suggested by below link I need to use createBrowserRouter
function .
why loader function not called in react js?
https://reactrouter.com/en/main/routers/picking-a-router
current way of routing.
export default function AppRoutes() {
return (
<Layout>
<Routes>
<Route element={<RequireAuth />}>
<Route
path={'/'}
element={
<React.Suspense
fallback={<div>loading</div>}
children={<Booking />}
/>
}
></Route>
</Route>
<Route element={<RequireAuth />}>
<Route
path={'/app'}
element={
<React.Suspense
fallback={<div>loading</div>}
children={<App />}
/>
}
></Route>
</Route>
</Routes>
</Layout>
);
}
I am trying to refactor my routing using createBrowserRouter
. I tried like this:
const router = createBrowserRouter([
{
path: '/',
loader: () => {
console.log('0000');
return 'ss';
},
element: <RequireAuth />,
},
{
path: '/app',
loader: () => {
console.log('0000');
return 'ss';
},
element: <RequireAuth />,
},
]);
How to render Booking
and App
components? How I will render children in createBrowserRouter
approach any idea?
Here is code sandbox demo: https://stackblitz.com/edit/vitejs-vite-6gg4ab?file=src%2FApp.tsx,src%2Fmain.tsx,src%2Findex.css,src%2Froutes.tsx,src%2Flayout.tsx,src%2FRequireAuth.tsx,src%2Fbrowser-routes.tsx&terminal=dev
The createBrowserRouter
function takes an array of RouteObject
types
export interface NonIndexRouteObject { caseSensitive?: AgnosticNonIndexRouteObject["caseSensitive"]; path?: AgnosticNonIndexRouteObject["path"]; id?: AgnosticNonIndexRouteObject["id"]; loader?: AgnosticNonIndexRouteObject["loader"]; action?: AgnosticNonIndexRouteObject["action"]; hasErrorBoundary?: AgnosticNonIndexRouteObject["hasErrorBoundary"]; shouldRevalidate?: AgnosticNonIndexRouteObject["shouldRevalidate"]; handle?: AgnosticNonIndexRouteObject["handle"]; index?: false; children?: RouteObject[]; element?: React.ReactNode | null; hydrateFallbackElement?: React.ReactNode | null; errorElement?: React.ReactNode | null; Component?: React.ComponentType | null; HydrateFallback?: React.ComponentType | null; ErrorBoundary?: React.ComponentType | null; lazy?: LazyRouteFunction<RouteObject>; } export type RouteObject = IndexRouteObject | NonIndexRouteObject;
The children
property takes another array of RouteObject
objects, so you can use this recursive structure to build up your routing hierarchy.
To convert the first code snippet using the BrowserRouter
to the new Data Router syntax I suggest the following refactor that:
Converts Layout
to a layout route component
Layout.tsx
import { Outlet } from 'react-router-dom';
export default function Layout() {
return (
<div>
Layout
<Outlet />
</div>
);
}
Renders a single layout route rendering RequireAuth
, this makes for code that is a bit more DRY
Renders Booking
and App
on nested routes under the auth layout route
routes.tsx
import {
createBrowserRouter,
Route,
} from 'react-router-dom';
const router = createBrowserRouter([
{
element: <Layout />,
children: [
{
element: <RequireAuth />,
children: [
{
path: '/',
loader: () => {
console.log('0000');
return 'ss';
},
element: (
<React.Suspense
fallback={<div>loading</div>}
children={<Booking />}
/>
),
},
{
path: '/app',
loader: () => {
console.log('0000');
return 'ss';
},
element: (
<React.Suspense
fallback={<div>loading</div>}
children={<App />}
/>
),
},
],
},
],
},
]);
export default router;
Update main.tsx to render a RouterProvider
and the computed router
instead of the BrowserRouter
component
main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { RouterProvider } from 'react-router-dom';
import './index.css';
import router from './routes';
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>
);