4

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?

Sagiv b.g
  • 26,049
  • 8
  • 51
  • 86
Asha
  • 3,001
  • 7
  • 40
  • 56

1 Answers1

7

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>
      );
    }
    
Sagiv b.g
  • 26,049
  • 8
  • 51
  • 86
  • Thanks for Answer. I made the changes as you suggested, no more errors. However now when I click on a route instead of seeing the component I see something like "React.lazy(() => import(`$./HomeB`))" instead of the component. – Asha Oct 25 '18 at 10:49
  • Sorry! Looks like I forgot to have {} around the React.lazy.. and it was being treated like a string. adding {}, I'm getting errors now. Can you have a look please? Thx https://codesandbox.io/s/3rv3yn0p5p – Asha Oct 25 '18 at 10:51
  • 1
    Check the update to the answer, by the way, wrapping it with `{}` won't make it a react element, you'll need to use JSX which is just a syntactic sugar for [React.createElement](https://reactjs.org/docs/react-api.html#creating-react-elements) – Sagiv b.g Oct 25 '18 at 11:00
  • 1
    I would recommend using the `render` prop of `Route` and not `component` since component calls React.createElement and if you put an inline function there, it will cause a re-render. You can see some more information here: https://reacttraining.com/react-router/web/api/Route/component – Matan Bobi Oct 25 '18 at 11:04