react:动态导入 jsx

IT技术 reactjs
2021-05-08 12:15:29

这个问题与将 JSX 文件动态导入 React 相关。

基本上,我们有一个主要组件,它根据存储在数据库中的结构动态呈现其他组件。动态组件存储在子目录“./Components”中。我们静态地将 this 定义为:

import CompA  from './Components/CompA';
import CompB  from './Components/CompB';

var components = {
 'CompA': CompA,
 'CompB': CompB
}

我们使用以下方法渲染它们:

var type = 'CompA' 
var Component = components[type];
...
<Component />

虽然这很好用,但对我们来说有点太静态了。我们有 100 多个组件(CompA/CompB)并且静态定义它们不起作用。

是否可以在“./Components”中导入所有 JSX 文件并填充组件数组?

而且,如果我们可以将“./Components”路径作为props发送到主要组件,那将会是真正(真的)好的。主要组件将使用此路径导入 .jsx 文件。像这样:

<MainComponent ComponentPath="./SystemComponents">

将使用“./SystemComponents”作为 .JSX 文件的路径,并且:

<MainComponent ComponentPath="./UserComponents">

将使用“./UserComponents”作为导入路径。

3个回答

拥有一个包含内容的 components/index.js 怎么样:

export CompA from "./comp_a";
export CompB from "./comp_b";

然后你做:

import * as Components from "./components"

那么你将使用为:

<Components.CompA />
<Components.CompB />
...

希望这可以帮助。

我怀疑在通过组件 props 发送路径时你可以加载任何东西,然后文件的加载应该发生在 React 组件生命周期方法中,这不是我推荐的。

React 16.6.0 开始,我们可以延迟加载组件并按需调用它们。

路由

// We pass the name of the component to load as a param
<Switch>
  …
  <Route path="/somewhere/:componentName" component={MyDynamicComponent} />
</Switch>

视图/index.js

import { lazy } from 'react';

const SomeView = lazy(() => import('./SomeView'));
const SomeOtherView = lazy(() => import('./SomeOtherView'));

export { SomeView, SomeOtherView };

我的动态组件.js

import React, { Suspense, Component } from 'react';
import { PropTypes } from 'prop-types';
import shortid from 'shortid'; // installed separately via NPM
import * as Views from './views';

class MyDynamicComponent extends Component {
  render() {
    const {
      match: {
        params: { componentName },
      },
    } = this.props;

    const Empty = () => <div>This component does not exist.</div>;
    const dynamicComponent = (() => {
      const MyComponent = Views[`${componentName}View`]
        ? Views[`${componentName}View`]
        : Empty;
      return <MyComponent key={shortid.generate()} />;
    })();

    return (
      <>
        <Suspense fallback={<div>Loading…</div>}>{dynamicComponent}</Suspense>
      </>
    );
  }
}
MyDynamicComponent.propTypes = {
  match: PropTypes.shape({
    params: PropTypes.shape({
      componentName: PropTypes.string.isRequired,
    }),
  }),
};

export default MyDynamicComponent;

用法

{items.map(item => (
  <NavLink to={`/somewhere/${item.componentName}`}>
    {item.name}
  </NavLink>
))}

为了补充@gor181 的回答,我可以补充说exports 必须是这样的:

export { default as CompA } from "./comp_a"; export { default as CompB } from "./comp_b";

希望这可能会有所帮助。