Force route order with react router

Viewed 27

I'm using react-router-dom v6. I want to force my app to follow an specific route order. This is my router file:

<Routes>
  <Route path="/" element={<DefaultLayout />}>
    <Route index element={<Home />} />
    <Route path="checkout" element={<Checkout />} />
    <Route path="success" element={<Success />} />
  </Route>
  <Route path="*" element={<Navigate to="/" />} />
</Routes>

I want the route order to be like:

  1. Only access checkout page from home
  2. Only acess success page from checkout

I know that I can do this by using useEffect(() => {/*check if it came from where spected, else return last page*/}, []) inside my components with somekind of history, to see if it matches. But I want to know if there is a way of doing this in my router file.

1 Answers

There isn't a way to just configure the routes to do this, you will need to check from where a user navigated from. This is basically a route protection question though. Create a custom Link component that sends the current location in route state, and a protected route component that checks this "from" location against an access list.

Example:

import { Link as BaseLink, useLocation } from 'react-router-dom';

const Link = ({ state, ...props }) => {
  const { pathname } = useLocation();
  return (
    <BaseLink
      {...props}
      state={{
        ...state,
        from: pathname
      }}
    />
  );
};

...

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

const AccessRoute = ({ accessFrom = [] }) => {
  const { pathname, state } = useLocation();
  const { from } = state || {};

  return [pathname, ...accessFrom].some((path) => path === from) ? (
    <Outlet />
  ) : (
    <Navigate to={from ?? "/"} replace />
  );
};

...

<Routes>
  <Route path="/" element={<DefaultLayout />}>
    <Route index element={<Home />} />
    <Route element={<AccessRoute accessFrom={["/"]} />}>
      <Route path="checkout" element={<Checkout />} />
    </Route>
    <Route element={<AccessRoute accessFrom={["/checkout"]} />}>
      <Route path="success" element={<Success />} />
    </Route>
  </Route>
  <Route path="*" element={<Navigate to="/" />} />
</Routes>

Edit force-route-order-with-react-router

Related