3

I have the following router config:

const router = createBrowserRouter([
  {
    element: <Layout />,
    loader: loaderFunction,
    children: [
      {
        path: '/home',
        element: <HomePage />
      },
      {
        path: '/about',
        element: <AboutPage />
      },
      {
        path: '/contact',
        element: <ContactPage />
      },
    ],
    errorElement: <ErrorPage />
  },
  {
    path: '*',
    element: <NotFoundPage />
  }
]);

This config has a <Layout /> parent, with several child routes (and their respective components).

The reasoning for this is that if a user enters any of those paths directly, the same behavior should occur.

Namely, the loaderFunction should fetch data. Then within the <Layout /> the data is parsed and analyzed... and then using the information the user is redirected using conditions like so:

if (conditionA && pathname !== '/about') {
  return <Navigate to="/about" replace />
}

if (conditionB && && pathname !== '/contact') {
  return <Navigate to="/contact" replace />
}

return <Outlet />;

The problem is that when a redirect points to one of those child components, the loaderFunction is re-triggered resulting in multiple server calls.

Is there a built-in way to manage this to avoid this problem? Or perhaps there is a better pattern for how to program this?

Nathan
  • 7,627
  • 11
  • 46
  • 80
  • I would suggest you set a state variable in in Layout that controls which component is rendered, after each there is a reload or navigation to any of the the children components. – Nicholas Mberev Dec 16 '22 at 04:37

1 Answers1

5

shouldRevalidate flag setting to false solves your problem;

It gives you control on preventing loader calls.

const router = createBrowserRouter([
  {
    element: <Layout />,
    loader: loaderFunction,
    shouldRevalidate: () => false,
  }
])  

documentation

  • This seems to do the trick. Do you know if there's a way to use a hook in the `shouldRevalidate` function? I'd like to access my global state, but it's only available through a hook. – Nathan Dec 16 '22 at 05:15
  • 2
    @Nathan Probably not. React hooks are only valid called in React functions and custom React hooks. – Drew Reese Dec 16 '22 at 05:16