How can I fix this Problem in React, that <Outlet /> works as it should?

43 Views Asked by At

I have a GameGuard which checks whether a user is logged in or not. If yes, you have access to the routes /game/*. My problem is that the context of the game component is displayed if you are on the path /game, but not if you are on the path /game/dashboard, although the same component should actually be displayed for both paths. However, if you replace return <Outlet />; with return <GameRouter />; in GameGuard, it works. Can anyone explain why this does not work with Outlet?

AppRouter:

const AppRouter = () => {
  return (
    <BrowserRouter>
      <Routes>

        <Route path="/game/*" element={<GameGuard />}>
          <Route path="/game/*" element={<GameRouter base="/game"/>} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
};

GameGuard:

export const GameGuard = () => {
  if (localStorage.getItem("token")) {
    
    return <Outlet />;
  }
  
  return <Navigate to="/login" replace />;
};

GameRouter:

const GameRouter = () => {
  return (
    <div style={{display: "flex", flexDirection: "column"}}>
      <Routes>

        <Route path="" element={<Game />} />

        <Route path="dashboard" element={<Game />} />

        <Route path="*" element={<Navigate to="dashboard" replace />} />

      </Routes>
   
    </div>
  );
};

I changed this:

        <Route path="/game/*" element={<GameGuard />}>
          <Route path="/game/*" element={<GameRouter base="/game"/>} />
        </Route

to:

        <Route path="/game/*" element={<GameGuard />}>
          <Route index element={<GameRouter base="/game"/>} />
        </Route

but that didn't work as well.

1

There are 1 best solutions below

0
Drew Reese On

You can't really have two routes that match the same. Index routes can not have children or render descendent routes. path="*" matches anything, while "*"` appended to any path allows descendent routes to be matched.

The following route configurations work though:

  • GameGuard layout route is pathless, GameRouter path uses wildcard matcher to allow descendent routes to be matched.

    <Routes>
      <Route element={<GameGuard />}>
        <Route path="/game/*" element={<GameRouter base="/game" />} />
      </Route>
    </Routes>
    
  • GameGuard layout route uses path "/game", GameRouter path is just wildcard matcher, any descendent route is matchable.

    <Routes>
      <Route path="/game" element={<GameGuard />}>
        <Route path="*" element={<GameRouter base="/game" />} />
      </Route>
    </Routes>