score:2

Accepted answer

The explanation is that the Switch component looks only at its direct children for the path property regardless of whether or not they are Routes.

In this case, since the direct child of Switch is User.Provider with no path property the switch will always just render that child (a switch will always render at least one child).

Now the children of User.Provider will be rendered, and the Switch will no longer have any bearing. This means now that the <Route path="*" /> will ALWAYS render like you are seeing.

Solution:

The solution is to just move the location of the User.Provider to surround the Switch component.

const Navbar = React.memo(props => {
    
    const [user, setUser] = React.useState(null);
    const value = React.useMemo(() => ({user, setUser}), [user, setUser]);
    const history = useHistory();
    
  return (
    <Router>
      <div>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/old-match">Old Match, to be redirected</Link>
          </li>
          <li>
            <Link to="/will-match">Will Match</Link>
          </li>
          <li>
            <Link to="/will-not-match">Will Not Match</Link>
          </li>
          <li>
            <Link to="/also/will/not/match">Also Will Not Match</Link>
          </li>
        </ul>
        <User.Provider value = {value}>
        <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>
        </User.Provider>
      </div>
    </Router>
  );
})

Related Query

More Query from same tag