React - 动态导入组件

IT技术 javascript reactjs import components react-component
2021-04-21 11:50:46

我有一个页面,它根据用户输入呈现不同的组件。目前,我已经对每个组件的导入进行了硬编码,如下所示:

    import React, { Component } from 'react'
    import Component1 from './Component1'
    import Component2 from './Component2'
    import Component3 from './Component3'

    class Main extends Component {
        render() {
            var components = {
                'Component1': Component1,
                'Component2': Component2,
                'Component3': Component3
            };
            var type = 'Component1';  // just an example
            var MyComponent = Components[type];
            return <MyComponent />
        }
    }

    export default Main

但是,我一直在更改/添加组件。有没有办法让文件只存储组件的名称和路径,然后将它们动态导入到另一个文件中?

6个回答

我认为可能对我试图实现的目标有些困惑。我设法解决了我遇到的问题,并在下面显示了我的代码,其中显示了我是如何解决它的。

单独的文件(ComponentIndex.js):

    let Components = {};

    Components['Component1'] = require('./Component1').default;
    Components['Component2'] = require('./Component2').default;
    Components['Component3'] = require('./Component3').default;

    export default Components

主文件(Main.js):

    import React, { Component } from 'react';
    import Components from './ComponentIndex';

    class Main extends Component {
        render () {
            var type = 'Component1'; // example variable - will change from user input
            const ComponentToRender = Components[type];
            return <ComponentToRender/>
        }
    }

    export default Main

这种方法允许我非常快速地添加/删除组件,因为导入位于一个文件中,并且一次只需要更改一行。

目的是在尽可能少更改代码的情况下加载新组件。这种方法只需要添加一行。
2021-05-29 11:50:46
你也可以做export { default as Component1 } from './Component1',然后import * as componentList from './ComponentIndex'componentList[type]
2021-06-09 11:50:46
你会如何在typescript中做到这一点?我有这个错误=>Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ ComponentCar: () => Element; }'. No index signature with a parameter of type 'string' was found on type '{ ComponentCar: () => Element; }'.ts(7053) 这来源于此命令const DynamicComponent = Components[Component],其中ComponentCar
2021-06-09 11:50:46
为什么我们.default再次访问
2021-06-13 11:50:46
非常感谢,这对我的问题最有效。我试图根据动态的配置文件呈现不同的组件。
2021-06-20 11:50:46

由于问题真的很老,所以答案可能还可以。但是现在,如果有人遇到同样的问题应该使用动态导入,以便只加载需要的组件并避免加载所有不同的组件。

const component = React.lazy(() => import('./component.jsx'));

试试这里的例子:演示

不错的答案,但值得注意的是 React.lazy 尚不可用于服务器端渲染。
2021-06-20 11:50:46
并且不可能使用完全动态的导入语句: webpack.js.org/api/module-methods/...
2021-06-20 11:50:46
import React, { Component } from 'react'
import Component1 from './Component1'
import Component2 from './Component2'
import Component3 from './Component3'

class Main extends Component {
    render() {
        var type = 'Component1';  // just an example
        return (
          <div>
            {type == "Component1" && <Component1 />}
            {type == "Component2" && <Component2 />}
            ...
          </div>
        )
    }
}

export default Main

您可以使用条件渲染插入。希望它会有所帮助

检查这个

简单的方法!解决了我的问题。当组件被使用时,我试图加载它。const Modal = lazy(() => import('./sharedmodule/common-modal/common-modal.component')); 上面的 Modal 块在 DOM 上渲染时就会被加载。因为我在做。return( <Modal showModal={popup}></Modal> // 这导致它立即渲染)
2021-06-19 11:50:46

这是另一个解决方案:我们获得所需组件的列表list = ['c1', 'c2', 'c3']它可以从 json 文件拉到一个数组中(我使用 redux-store 所以我开始通过 this.props.getForms() 获取表单)。但是您可以手动创建和访问组件列表。

    componentDidMount = () => {
//we get elements list from any source to redux-store
        this.props.getForms();
//access redux-store to the list
        const forms = this.props.configBody.sets;
//make deep object copy
        const updatedState = { ...this.state };
        updatedState.modules = [];
        if (forms) {
//here is the very dynamic import magic: we map the import list and prepare to store the imports in Component`s state
            const importPromises = forms.map(p =>
                import(`../TemplateOrders/Template${p.order}`)
                    .then(module => {
                        updatedState.modules.push(module.default)
                    })
                    .catch(errorHandler(p))
            )
//wait till all imports are getting resolved
            Promise.all(importPromises)
                .then(res =>
//then run setState
                    this.setState({ ...updatedState }, () => {
                        console.log(this.state);
                    }))
        }
    }

    render() {
        const forms = this.props.configBody.sets;
//we iterate through the modules and React.createElemet`s 
        const list = this.state.modules
            ? this.state.modules.map((e, i) =>
                createElement(e, { key: forms[i].title }, null)
            )
            : [];
        return (
            <Fragment>
                <Link to='/'>Home</Link>
                <h1>hello there</h1>
//push them all to get rendered as Components
                {list.map(e => e)}
            </Fragment>
        )
    }

因此,当您的应用程序加载时,它会拉取所需的module。

我想使用Promise来导入它们,但是module已经是 Promise 了。

在情况下,我们需要从最近的服务器Ajax它们,所以我们需要绑定前的module分割要求(或类似的东西),不知道到底。

您可以将您的组件捆绑为微应用程序,并从 url 将它们热加载到您的应用程序中。这是一个支持从基于站点级别配置的路由动态导入组件和微应用程序的 poc。

https://github.com/eschall/react-micro-frontend

我查看了您的 poc,但由于我从未使用过 redux,因此我不太了解它。我想从外部 api 导入反应组件。结果可以被预处理等。我只是想知道这是否可能。我确实在这里问过这个问题stackoverflow.com/q/59018834/6394630也许你可以看看
2021-05-22 11:50:46