8

Am using react router v6 and i would like to use the new loader to load the data before the component loads. So i have the following

In my index.js

const router = createBrowserRouter(
createRoutesFromElements(
    <Route path="*"
           loader={async ({ params }) => {

               console.log("index loader log"); //this logs

               return true;
           }}
           element={<App />}
     > </Route>
  )
);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <RouterProvider router={router} />
);

in my app component i have nested routes like

const App = () => {
 return (
     <>
        <Routes>
            <Route path="auth/*" element={<AuthLayout/>}/>
            <Route path="about"
             loader={async ({ params }) => {

               console.log("about child loader log"); //this doesnt log

               return true;
              }}
           element={<AboutPage/>}/>
        </Routes>
        <h1>Testing app</h1>
     </>

   );

 }

On the app component the loader on the Route path="about" does not console.log when i visit the about route but the component is rendered. What am i missing for the loader to work on the child route.

1 Answer 1

10

Based on some basic testing it seems that in order for the new RRDv6.4 data APIs to work you need to specify the complete routing configuration in the createBrowserRouter function.

There does however appear to already be an issue filed with @remix-run/react-router for this behavior as a reported bug, so you may want to follow it if it ever addressed/resolved. (I suspect it was you since the name is "geoffrey" and the timing is coincidentally about an hour ago around the same time as this post)

This above issue has since been closed with comment:

Descendant <Routes> trees do not participate in data loading (https://reactrouter.com/en/main/components/routes) since they cannot be known ahead of render-time. You'll need to lift your descendant route definitions up into the routes you pass to createBrowserRouter.

The relevant information regarding the descendent routes and the new Data API can be found in the Routes documentation in a note.

Note:

If you're using a data router like createBrowserRouter it is uncommon to use this component as it does not participate in data loading.

Hoist the entire route declaration to the parent creating the data router. The following does work with the loader function for the "/about" route and About component.

const router = createBrowserRouter(
  createRoutesFromElements(
    <Route
      path="*"
      loader={({ params }) => {
        console.log("index loader log");

        return "This is the App";
      }}
      element={<App />}
    >
      <Route path="auth/*" element={<AuthLayout />} />
      <Route
        path="about"
        loader={({ params }) => {
          console.log("about child loader log");

          return "this is the about page";
        }}
        element={<AboutPage />}
      />
    </Route>
  )
);

The App component should render an Outlet for the nested routes to render their content into.

import { Outlet } from 'react-router-dom';

const App = () => {
  return (
    <>
      <h1>Testing app</h1>
      <Outlet />
    </>
  );
};

Edit react-router-route-loader-not-working-on-nested-components

enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

I can confirm that changing from using <Routes/> to <Outlet /> and specifying the whole routing configuration createBrowserRouter worked for me as a workaround.
Yes this does work by lifting the routes at the top.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.