ConfuedProblemSolver
ConfuedProblemSolver

Reputation: 653

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.

Upvotes: 2

Views: 799

Answers (2)

Ben Smith
Ben Smith

Reputation: 20230

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.

Upvotes: 3

Rohan Agarwal
Rohan Agarwal

Reputation: 2609

Try using a ternary operator instead of an And operation

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>
)

Upvotes: 0

Related Questions