Search code examples
javascriptreactjsreact-routerreact-router-dom

Parent Loader function being called on every child route redirection


My use case is

Router_configuration.js

import { createBrowserRouter, RouterProvider } from "react-router-dom";
import Product, { loader } from "./Product";
import Route1 from "./Route1";

const router = createBrowserRouter([
  {
    path: "/",
    element: <Product />,
    loader: loader,
    children: [
      {
        path: "routeone",
        element: <Route1 />
      }
    ]
  }
]);

const App = () => {
  return <RouterProvider router={router} />;
};

export default App;

Product.js

import Header from "./Header";
import { Outlet } from "react-router-dom";
import Router from "./Router";

const Product = () => {
  return (
    <>
      <Header />
      <Outlet />
      <Router />
    </>
  );
};

export default Product;

export const loader = () => {
  console.log("loader");
  return -1;
};

Header.js

const Header = () => {
  return <p>Header</p>;
};

export default Header;

Route1.js

import { NavLink } from "react-router-dom";

const Router = () => {
  return (
    <>
      <NavLink to={"routeone"}>
        <span> Route 1</span>
      </NavLink>
    </>
  );
};

export default Router;

Before loading each child route, I require specific data to be loaded. Therefore, I utilize the loader of the parent route. It appears that clicking the NAVLink twice (Surprisingly only on double click not on single click over the NAVLink), which routes to the child route, triggers my parent loader. My intention is for the parent route's loader to be invoked only once, regardless of internal redirection.

But if im having shouldRevalidate: () => false, seems fixing the issue. Is that the correct way or do im missing something?


Solution

  • There are a handful of reasons why a route loader would be called again, e.g. revalidates the route data, after the initial route loading. I've highlighted the case you are hitting below.

    There are several instances where data is revalidated, keeping your UI in sync with your data automatically:

    • After an action is called from a .
    • After an action is called from a <fetcher.Form>
    • After an action is called from useSubmit
    • After an action is called from a fetcher.submit
    • When an explicit revalidation is triggered via useRevalidator
    • When the URL params change for an already rendered route
    • When the URL Search params change
    • When navigating to the same URL as the current URL

    If you want the root "/" route to load only once, the first time the route loads, then specifying the shouldRevalidate prop and returning false will accomplish calling the loader only once, and not on any subsequent time the app navigates to the same current URL path.