Edgar Barber
Edgar Barber

Reputation: 385

Nested route not found with react-router

Here is my code

const AppRoutes: FC = () => {
  const {currentUser, fetchingAuth} = useAuth()

  let route
  if (fetchingAuth || !currentUser) {
    route = <Route path='*' element={null}></Route>
  } else {
    route = (
      <>
        <Route path='/' element={<OptInPage />} />
      </>
    )
  }

  return (
    <MemoryRouter>
      <Routes>{route}</Routes>
    </MemoryRouter>
  )
}

OptInPage

const OptInPage = () => (
  <Routes>
    <Route element={<OptInLayout />}>
      <Route path='opt-in' element={<OptIn />} />
      <Route path='get-items' element={<GetItems />} />
      <Route index element={<OptIn />} />
    </Route>
  </Routes>
)

When I try to navigate to /get-items, the route is not found, however when I change AppRoutes to be the following

const AppRoutes: FC = () => {
  const {currentUser, fetchingAuth} = useAuth()

  let route
  if (fetchingAuth || !currentUser) {
    route = <Route path='*' element={null}></Route>
  } else {
    route = (
      <Route element={<OptInLayout />}>
        <Route path='opt-in' element={<OptIn />} />
        <Route path='get-connections' element={<GetConnections />} />
        <Route index element={<OptIn />} />
      </Route>
    )
  }

  return (
    <MemoryRouter>
      <Routes>{route}</Routes>
    </MemoryRouter>
  )
}

It does work, am I missing something? how come when the component is nested, the route is not found

Upvotes: 1

Views: 265

Answers (1)

Drew Reese
Drew Reese

Reputation: 202605

The second code example/snippet works because it is rendering the routes and nested routes directly, as opposed to the first example/snippet's rendering of descendent routes and the root route not allowing descendent route matching.

The issue is that AppRoutes is only rendering a route and OptInPage on exactly path="/". If you want <Route path='/' element={<OptInPage />} /> to also match and render descendent routes (rendered by any nested Routes components) then append the "*" wildcard matcher to the parent route's path.

Example:

const AppRoutes: FC = () => {
  const { currentUser, fetchingAuth } = useAuth();

  let route;
  if (fetchingAuth || !currentUser) {
    route = <Route path='*' element={null} />;
  } else {
    route = <Route path='/*' element={<OptInPage />} />;
  }

  return (
    <MemoryRouter>
      <Routes>
        {route}
      </Routes>
    </MemoryRouter>
  );
};

...

const OptInPage = () => (
  <Routes>
    <Route element={<OptInLayout />}>
      <Route path='opt-in' element={<OptIn />} />
      <Route path='get-items' element={<GetItems />} />
      <Route index element={<Navigate to="opt-in" replace />} />
    </Route>
  </Routes>
);

Upvotes: 1

Related Questions