Home > Enterprise >  React: Cannot Import a Module Based on an If Statement: Objects are not valid as a React child (foun
React: Cannot Import a Module Based on an If Statement: Objects are not valid as a React child (foun

Time:09-26

I am trying to import a module in react, based on an if condition. I have read that the import statement returns a promise. However, I cannot find a way to solve this. The code works when I import the module statically, but it does not work with dynamic import:

list.js

// import WelcomeGuide from './guide'; //this one works
const show_deprecated_guide = '';

const WelcomeGuide = (props) => ( // this one throws an error
    import(`${!show_deprecated_guide ? `./guide.js` : `./guide-deprecated.js`}`)
        .then( (Module) => (
            Module.default
        )
        )
        .catch ((err) => (
            console.log(err)
        )
    )
)

const WelcomeList = (props) => {

    // loading state..
    if (!posts) return <div className="guide-list"><Spinner /></div>;


    // loaded state
    return (
        <Fragment>
                <WelcomeGuide/>
        </Fragment>
    )
};

export default WelcomeList;

guide.js

const WelcomeGuide = (props) => {

  return (
    <p>Welcome!</p>
  )
}

export default WelcomeGuide;

I know I can jut import both components statically and render them conditionally, but it seems better for performance if I can import them based on the data I have. So, my question is: How to correctly import the module when using if statement? I read a lot of tutorials and I understand that the error is pretty self-explanatory, but I still cannot solve this one. Any help will be appreciated!

CodePudding user response:

I'm not 100% sure to understand your problem but I would say you need to import both guides and use the condition on the render like that :

import Guide from './...'
import DeprecatedGuide from './...'

const WelcomeList = ({ show_deprecated_guide }) => {
  return (
    <div>
      { show_deprecated_guide ? <DeprecatedGuide /> : <Guide /> }
    </div>
  )
}

CodePudding user response:

That's definitely not how you render a component in react.

If this is to work, it should look something like:

const WelcomeGuide = (props) => ( // this one throws an error
    import(show_deprecated_guide ? './guide.js' : './guide-deprecated.js')
        .then((Module) => (<Module />))
        .catch ((err) => {
            console.log(err)
        }
    )
)

Moreover, react already has a solution for doing things like that. It comes as a utility function: lazy

To use it in this case, you can do something like:

const Guide = React.lazy(() => import('./guide.js'));
const GuideDeprecated = React.lazy(() => import('./guide-deprecated.js'));
const WelcomeGuide = (props) => (
    <Suspense fallback={<div>Loading...</div>}>
        show_deprecated_guide ? (<Guide />) : (<GuideDeprecated />)
    </Suspense>
)

Note the use of Suspense around the lazy loaded components. You can have Suspense further up in the tree and it will still work.

Read more about code splitting here

  • Related