5

I am trying to load a components inside of a Tab component for react. The Idea is have a json ( or better yaml) with this syntanx:

interface TabType {
    name: string;
    components: string[];
}

interface Templates {
    tabs: TabType[];
}

const templateTabsModules: Templates = {
    tabs: [
        {
            name: "Title for Tab 1",
            components: ["./components/OneComponent"]
        },
        {
            name: "Title for Tab 2",
            components: ["./components/TwoComponent"]
        }
    ]
};

So inside of the Main Component do something like:

<Tabs id="tab">
   {templateTabsModules.tabs.map(tab => {
      return (
        <Tab title={tab.name}>
          <p>The component should appears bellow:</p>
          <Suspense fallback={<div>Loading</div>}>
           {tab.components.map(component => {
              const Comp = lazy(() => import(component));
              return (<Comp />)
           })}
          </Suspense>
         </Tab>
       );
    })}
</Tabs>

But this code does not work, I could see that if I use just the path as string by doing const Comp = lazy(() => import('./components/OneComponent')); it works, but does not if I use the dynamic variable.

2 Answers 2

5

I found a possible solution that does what I need without declare before the components by doing:

<Tabs id="tab">
  {templateTabsModules.tabs.map((tab, index) => {
     return (
        <Tab title={tab.name} key={index}>
            <p>The component should appears bellow:</p>
            <Suspense fallback={<div>Loading</div>}>
             tab.components.map(component => {
               const Comp = lazy(() => import(
                 /* webpackChunkName: "my-chunk-name" */
                 /* webpackMode: "lazy" */
                 `${component}`
               ).then(comp => comp));

               return (<Comp />)

             })}
            </Suspense>
        </Tab>
      );
   })}
</Tabs>

So Webpack can load the component and return it as promise

Example -> https://codesandbox.io/s/lazy-components-with-react-mix9y

Sign up to request clarification or add additional context in comments.

Comments

3

Webpack is trying it's best to exclude all the files that you don't need.

I think it should work if you define your consts before and reference them in your loop

const Comp1 = lazy(() => import('./components/OneComponent'));
const Comp2 = lazy(() => import('./components/TwoComponent'));

...

tabs: [
    {
        name: "Title for Tab 1",
        component: Comp1
    },
    {
        name: "Title for Tab 2",
        component: Comp2
    }
]

...

      <Suspense fallback={<div>Loading</div>}>
       {tabs.map(tab => tab.component)}
      </Suspense>

3 Comments

Hello Jonathan! thanks for the answer. That would be one solution yes, but we will need to create before all those components, I wanted to avoid this step.
@RubénFanjulEstrada I don't think you can do it completely dynamically like that - webpack won't know to include those files in your bundle.. I don't understand the need to do it completely dynamically - it's not like you are creating those files on the fly. I think there might be something wrong with the approach - perhaps compose your components differently to avoid this issue
Wow it's worked! Look at splitting codes here: fatihmert.dev/stackoverflow/code-split-react.png

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.