Search code examples
javascriptreactjsreact-routerswitch-statementurl-routing

React Router Switch routes not being matched


Working on client-side routing using react 16.13.1 & react-router 5.1.2, and having some routing issues.

First I have a Switch component with several children Route components (as shown below) and everything routes as expected. Paths that do not match any of my specific routes fall through to the catch-all route.

<Switch>
  <Route exact path="/">
    <Home />
  </Route>
  <Route path="/old-match">
    <Redirect to="/will-match" />
  </Route>
  <Route path="/will-match">
    <WillMatch />
  </Route>
  <Route path="*">
    <NoMatch />
  </Route>
</Switch>

Next I want to make some of the routes private so only logged in users can access them. I have seen several examples of custom PrivateRoute components but when I implement them, I seem to have the same problem each time ... any routes defined after the private route is never successfully matched. I have put together a simplified version of my code that uses an isAuthenticated variable inline to render some conditional components as shown here:

const isAuthenticated = true;

<Switch>
  <Route exact path="/">
    <Home />
  </Route>
  {isAuthenticated && (
    <>
      <Route path="/old-match">
        <Redirect to="/will-match" />
      </Route>
      <Route path="/will-match">
        <WillMatch />
      </Route>
    </>
  )}
  <Route path="*">
    <NoMatch />
  </Route>
</Switch>

The catch-all route is never matched because it is after the private fragment. What am I doing wrong here? I have a sandbox of this simplified example at https://codesandbox.io/s/react-router-test-fzl22. Any help is appreciated.


Solution

  • The React fragment tags are breaking the Switch statement. If you refactor your code to:

    <Switch>
        <Route exact path="/">
            <Home />
        </Route>
        {isAuthenticated && (
            <Route path="/old-match">
                <Redirect to="/will-match" />
            </Route>
        )}
        {isAuthenticated && (
            <Route path="/will-match">
                <WillMatch />
            </Route>
        )}
        <Route path="*">
            <NoMatch />
        </Route>
    </Switch>
    

    the code works fine.

    You can see this working in a fork of your sandbox here.