4

So following dynamic loading works fine:

return React.lazy(() => import("./hotels/components/" + componentName));

Following does not work:

const path = "./hotels/components/";
return React.lazy(() => import(path + componentName));

Now i think it might have something to do with the minifier since in the case where it works "import" turns blue in vscode. In case where it doesn't work "import" is yellow.

Also when i compile for the case where it doesn't work i get following warning:

Critical dependency: the request of a dependency is an expression

Has anyone ran into this issue?

I tried everything from this similar question:

Webpack - Critical dependency: the request of a dependency is an expression

4

3 Answers 3

3

Following solved the error and got rid of the warning. Just had to embed variable.

return React.lazy(() => import(`${path + componentName}`));
Sign up to request clarification or add additional context in comments.

Comments

0

In my situatuion with TypeScript i had to do separate function in getComponent.ts

src -> Utils -> getComponent.ts

import React, { lazy } from 'react';

type Component = React.LazyExoticComponent<React.ComponentType<any>>;
const componentCache: Record<string, Component> = {};

/**
 * Retrieves a component based on a relative path from the ./src/ directory.
 *
 * @param {string} path - Relative path from the ./src/ directory.
 * @param {string} name - Component name.
 */
export default function getComponent(path: string, name: string): any {
    if (!componentCache[name]) {
        componentCache[name] = lazy(() => import(`../${path}`));
    }

    return componentCache[name];
}

And we can use it like that:

 {tabs.map((el, index) => (
    <Box key={index}>
        <React.Suspense fallback={<>...</>}>
            {React.createElement(
                getComponent(el.componentSrc, el.componentName)
            )}
        </React.Suspense>
    </Box>
))}

Data in tabs

export const importerTabs: any[] = [
    {
        componentName: 'FirstCompoent',
        componentSrc: 'Pages/FirstPage/FirstCompoent',
    },
    {
        componentName: 'SecondComponent',
        componentSrc: 'Pages/SecondPage/SecondComponent',
    }
];

Comments

0

There seems to be two problems in one here, which may be causing confusion.

First, there is the Webpack issue with dynamic expressions, as defined here (thanks for your comment, @Eric). That seems to be a transpiler issue. Webpack even complains about module-level const values which would never change, so I guess it can't easily interpret context.

Second, I got caught out a few times with relative paths while using import(). The paths have to be relative to where the import call is being made.

//src/utils/helper.js
function doImport(pathString) {
  import(`${pathString}`).then(handleTheReturnedModule);
}

//src/rendering/Component.jsx
/* Here the coder wants to use `src/rendering/SubComponent` */
doImport("./SubComponent"); // Oops! import looks for `src/utils/SubComponent`

FWIW, a workaround for helper functions is to pass the Promise instance, rather than the pathString:

//src/utils/helper.js
function doImport(promise) {
  promise.then(handleTheReturnedModule);
}

//src/rendering/Component.jsx
/* Now import uses the same relative path as Component, as expected.*/
doImport(import("./SubComponent"));

Comments

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.