0

Maybe there is a better way, but I try to make my React components as reusable as possible. So I am using a bootstrap Card and inside this Card I wanna place different components from outside (with props) dynamically. Without props it works fine. But with props I got an error message "Error: Cannot find module '../../pages/Dummy'".

This works perfect:

import React, {Suspense} from 'react';
import { MDBCard, MDBCardBody } from "mdbreact";

const Area = (props) => {

    const OtherComponent = React.lazy(() => import('../../pages/Dummy'));

    return (
            <MDBCard className="text-center">
                <MDBCardBody>
                    <Suspense fallback={<div>Loading...</div>}>
                        <OtherComponent/>
                    </Suspense>
                </MDBCardBody>
            </MDBCard>
    );
};

export default Area;

This doesn't work:

import React, {Suspense} from 'react';
import { MDBCard, MDBCardBody } from "mdbreact";

const Area = (props) => {

    const OtherComponent = React.lazy(() => import(props.compName));

    return (
            <MDBCard className="text-center">
                <MDBCardBody>
                    <Suspense fallback={<div>Loading...</div>}>
                        <OtherComponent/>
                    </Suspense>
                </MDBCardBody>
            </MDBCard>
    );
};

export default Area;

Call from outside:

<Area compName='../../pages/Dummy'/>

It's like I cannot lazy-load with props. Very strange.

Btw. I don't need to use lazy-loading if there is an easier way to use sub-components dynamically. I just thought this is the only way.

Jee Mok
  • 6,157
  • 8
  • 47
  • 80
Andrew
  • 15
  • 3

1 Answers1

0

There are a few options:

The first one uses 'slots,' which you can read about in the React docs here, or an article here.

const DummyOne = React.lazy(() => import('../../pages/DummyOne');
const DummyTwo = React.lazy(() => import('../../pages/DummyTwo');

const Area = ({ comp }) => {
  return (
    <MDBCard className="text-center">
      <MDBCardBody>
        <Suspense fallback={<div>Loading...</div>}>
          {comp}
        </Suspense>
      </MDBCardBody>
    </MDBCard>
  );
}

// You dynamically pass the component itself into 'Area'
<Area comp={<DummyOne />} />

The second option is closer to what you have:

const Area = ({ compName }) => {
  const components = {
    DummyOne: React.lazy(() => import('../../pages/DummyOne'),
    DummyTwo: React.lazy(() => import('../../pages/DummyTwo'),
  }

  const DynamicComponent = components[compName];

  return (
    <MDBCard className="text-center">
      <MDBCardBody>
        <Suspense fallback={<div>Loading...</div>}>
          <DynamicComponent />
        </Suspense>
      </MDBCardBody>
    </MDBCard>
  );
}

// You dynamically pass the component name to 'Area' as a string
<Area compName="DummyOne" />
helloitsjoe
  • 6,264
  • 3
  • 19
  • 32