skip to Main Content

Given routes like this:

<Routes>
  <Route element={<MainLayout />}>
    <Route path="foo/:token" element={<Foo />} />
    <Route path=":token" element={<Bar />}>
      <Route path=":id" element={<Baz />}>
    <Route>
  </Route>
</Routes>

How can MainLayout know which route was resolved? I need to know if it was within the route tree with path=":token".

useMatch('/:token/*') does not work because it matches on path foo/123, which resolves to the path="foo/:token" route.

I can’t figure out what useResolvedPath does or how I could use it. I just seems to echo the input param.

I can’t use const { token } = useParams() since both routes have a param named token.

Ideas?

2

Answers


  1. Chosen as BEST ANSWER

    I was thinking about this wrong, and my question did not explain the context well enough to spot it.

    MainLayout contains global nav elements that I want to be slightly different for different routes. Rather than have MainLayout look outward at the route, the router setup should tell MainLayout what to do. Like this:

    <Routes>
      <Route element={<MainLayout />}>
        <Route path="foo/:token" element={<Foo />} />
      </Route>
      <Route element={<MainLayout someParam={paramValue} />}>
        <Route path=":token" element={<Bar />}>
          <Route path=":id" element={<Baz />}>
        <Route>
      </Route>
    </Routes>
    

    Where MainLayout uses paramValue to behave differently.


  2. It seems the issue, or question, is really about how to differentiate between the two routes that defined identical path parameter variables. In other words, you are trying to check which route the token path param was populated from.

    My suggestion here would be to use different path parameter variable names to disambiguate them.

    For example fooToken and barToken:

    <Routes>
      <Route element={<MainLayout />}>
        <Route path="foo/:fooToken" element={<Foo />} />
        <Route path=":barToken" element={<Bar />}>
          <Route path=":id" element={<Baz />}>
        <Route>
      </Route>
    </Routes>
    

    The MainLayout component can check for both and conditionally apply logic.

    const { barToken, fooToken } = useParams();
    
    ...
    
    useEffect(() => {
      if (barToken) {
        // bar token logic
      }
    
      if (fooToken) {
        // foo token logic
      }
    
    }, [barToken, fooToken]);
    ...
    

    An alternative would be to use the useMatch hook and explicitly check for a match for each route that has a token path parameter.

    const MainLayout = () => {
      const fooMatch = useMatch("/foo/:token"); // foo token
      const barMatch = useMatch("/:token");     // bar token
      const bazMatch = useMatch("/:token/:id"); // bar token
    
      useEffect(() => {
        console.log({ fooMatch, barMatch, bazMatch });
    
        if (barMatch || bazMatch) {
          // bar token logic
        }
    
        if (fooMatch) {
          // foo token logic
        }
    
      }, [fooMatch, barMatch, bazMatch]);
    
      return (
        <>
          ...
          <Outlet />
        </>
      );
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search