Description
Version
5.1.2 (not tested on previous versions)
Test Case
https://codesandbox.io/s/react-router-t0ig4
Steps to reproduce
Please see above CodeSandbox.
Expected Behavior
Using React Router with Suspense/lazy.
const Home = () => <div>I am not lazy loaded</div>;
const About = React.lazy( () => import('./About.js') );
const App = () => (
<Router>
<div>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</div>
<Suspense fallback="Loading...">
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
</Switch>
</Suspense>
</Router>
);
Home
is a normal component, About
is lazy-loaded.
When you click "About" link, "Loading..." should appear (it does).
Now, while About
is still loading, if you click "Home" link, the page should update immediately and show you the "Home" page again.
Actual Behavior
In fact, the route transition back to "Home" is delayed until About
has finished loading.
This is hard to spot in a dev environment, as About
will load quickly anyway. So in the CodeSandbox above I've substituted a fake Lazy component which never loads. The result is that the page is stuck on "Loading..." forever - navigation ceases to work.
Two things solve the problem:
- Add a
useLocation()
somewhere below the<Switch>
element to force<Switch>
to re-render on a route transition. - Remove the
<Switch>
entirely. If it's just a series of<Route>
elements, it works as expected.
I have played around with this a lot, and can't figure out if it's a bug in React Router, or in React's handling of Context within Suspense. But I figured I'd post this here first.