Search code examples
reactjsreact-routerreact-lazy-load

componentDidMount unexpectedly called after move from react-loadable to react.lazy


In my project I used to rely on react-loadable to do some code spliting, lazy loading together with react-router. Something like:

<Route component={component} />

with

Component = Loadable({
    loader: () => import(/* webpackChunkName: "Analyze" */ "./components/Analyze"),
})

The Analyze component implements componentDidMount and use router's history.push on state change. When a new url is pushed with some parameter changed, but still leading to this same "Analyze" component, only componentDidUpdate is called. I updated this code to use React.lazy:

<Route component={(_props: any) =>
          <LazyComponentWrapper>
              <Component {..._props} />
          </LazyComponentWrapper>
        } />

with

Component = React.lazy(() => import(/* webpackChunkName: "Analyze" */ "./components/Analyze")),

and

function LazyComponentWrapper({ children }) {
  return (
    <Suspense fallback={<div>{LOADING}</div>}>
        {children}
    </Suspense>
  );

but now componentDidMound is unexpectedly called every time. It's not clear to me wether this have to do with React.lazy or with react-router. Any clue ?


Solution

  • According to docs maybe its better to move Suspense out of Route component, try this:

    import React, { Suspense, lazy } from 'react';
    import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
    
    const Home = lazy(() => import('./routes/Home'));
    const Component = React.lazy(() => import(/* webpackChunkName: "Analyze" */ "./components/Analyze"))
    
    const App = () => (
      <Router>
        <Suspense fallback={<div>Loading...</div>}>
          <Switch>
            <Route exact path="/" component={Home}/>
            <Route path="/analyze" component={Component}/>
          </Switch>
        </Suspense>
      </Router>
    );