Languages
[Edit]
EN

React - import component dynamically

13 points
Created by:
AnnLen
12400

In this short article, we would like to show how to import components dynamically in React.

Quick solution:

const MyComponent = React.lazy(() => import('./Mycomponent'));

Custom component import logic

This section shows how to create custom logic that loads indicated component when the first time is used.

That kind of component attaching can be useful when:

  • we don't want to load all web application logic until some part of them is used,
  • component logic is located on a different server,
  • when we use Server-Side Rendering (SSR), the attached component uses BOM (Browser Object Model, like: window, location, navigator, etc.) and┬áwe want to avoid internal problems with undefined BOM objects in compilation with NodeJS (SSR in Gatsby has problems with JS libraries that calls window, location, nagator, etc.).

Note: below example shows how to create useComponent hook that let us to load component with async import - be sure that building tool is configured to compile separated bundle that contains desired component.

Quick solution (useComponent.jsx file):

import { useState } from 'react';

let componentPromise = null;
let componentModule = null;

// the method runs component import only once 
// with waiting until operation is completed for other calls
const importComponent = () => {
    if (componentModule) {
        return Promise.resolve(componentModule);
    }
    if (componentPromise) {
        return componentPromise;
    }
    componentPromise = import('/path/to/my/component') // change it to something
        .then((module) => {
            componentModule = module;
            return module;
        }));
    return componentPromise;
};

// uncomment below line to start module loading as soon as it possible
// loaded module before do not cause re-rendering / state changes later
//prepareComponent();

const useComponent = () => {
    const [component, setComponent] = useState(componentModule);
    if (component === undefined) {
        importComponent()
            .then(setComponent)    // we just wait until component is ready
            .catch(console.error); // we want to see loading exceptions in console
    }
    return component;
};

export default useComponent;

Usage example:

import React from 'react';
import useComponent from './useComponent';

const App = () => {
  const Component = useComponent();
  return (
    <div>
      {Component ? <Component.default /> : <span>Component is not imported yet!</span>}
    </div>
  );
};

export default App;

Note: change Component.default to proper export name if it is necessary.

Example import names:

static importdynamic import
import MyComponent from './my-component';const Component = useComponent();
const MyComponent = Component.default;
import {MyComponent1, MyComponent2}
from './my-component';

const Component = useComponent();
const MyComponent1 = Component.MyComponent1;
const MyComponent2 = Component.MyComponent2;

Universal component import logic

In this section we would like to show how to modify above logic to import different components indicating component paths.

import { useState } from 'react';

const statuses = { }; // keeps information about imported modules

// the method runs component import only once 
// with waiting until operation is completed for other calls
const importComponent = (path) => {
    const status = statuses[path];
    if (status.module) {
        return Promise.resolve(status.module);
    }
    if (status.promise) {
        return status.promise;
    }
    status.promise = import(path)
        .then((module) => {
            status.module = module;
            return module;
        }));
    return status.promise;
};

// uncomment below line to start module loading as soon as it possible
// loaded module before do not cause re-rendering / state changes later
//prepareComponent();

const useComponent = (path) => {
    const [component, setComponent] = useState(() => {
        const status = statuses[path];
        return status ? status.module : undefined;
    });
    if (component === undefined) {
        importComponent(path)
            .then(setComponent)    // we just wait until component is ready
            .catch(console.error); // we want to see loading exceptions in console
    }
    return component;
};

export default useComponent;

Usage example:

import React from 'react';
import useComponent from './useComponent';

const App = () => {
  const Component = useComponent('/path/to/my/component'); // change it to something
  return (
    <div>
      {Component ? <Component.default /> : <span>Component is not imported yet!</span>}
    </div>
  );
};

export default App;

Note: some transpilers resolves import('/literal/as/path/to/component/module') paths during transpilation that makes impossible to use variables with import, e.g. import(pathToMyComponentModule) - Gatsby has that. The solution for the problem is to edit the above code and replace the path with a callback that returns the import result. Finally, we should use: const Component = useComponent(() => import('/path/to/my/component'));

ReactJS

React - import component dynamically
Native Advertising
­čÜÇ
Get your tech brand or product in front of software developers.
For more information Contact us
Dirask - we help you to
solve coding problems.
Ask question.

ÔŁĄ´ŞĆ­čĺ╗ ­čÖé

Join