Search code examples
javascriptreactjsreact-router-v4react-async

Dynamic Lazy Loading using React.Lazy (16.6.0)


I get an array like

{Path:xxx, 
Component:"./xxx/ComPXX"}

from my API and based on that create my application's routes. At the moment I'm using React-Loadable (5.5.0) and React-Router (4.4.0-betax to avoid warnings in strict mode). See working example here.

Since React 16.6 has introduced React.lazy, I'm trying to migrate my solution, however I'm facing errors and difficulties however I try to do this. You can see migrated (failing) code here.

Any Idea why this isn't working? Can it be because React.Lazy doesn't accept variables?


Solution

  • You got 2 3 main issues:

    1. In this line:

      var c = <dynamicLoader component={prop.component} />;
      

      User-Defined Components Must Be Capitalized. so change it to this:

      var c = <DynamicLoader component={prop.component} />;
      

      Obviously you'll need to change the declaration as well:

      function DynamicLoader(props) {
        return (
          <Suspense fallback={<div>Loading...</div>}>
            React.lazy(() => import(`${props.component}`))
          </Suspense>
        );
      }
      
    2. In this line

      return <Route exact path={prop.path} component={c} key={key} />;  
      

      As the name of the prop component suggests, you need to pass a component and not an element you can read more about the difference in the DOCS.

      So you'll need to change it to this:

      return <Route exact path={prop.path} component={() => c} key={key} />;
      
    3. You are right. I missed the children part, you are rendering a string. You can create a variable and just render it as the child:

      function DynamicLoader(props) {
        const LazyComponent = React.lazy(() => import(`${props.component}`));
        return (
          <Suspense fallback={<div>Loading...</div>}>
            <LazyComponent/>
          </Suspense>
        );
      }