【问题标题】:React: dynamic import jsxReact:动态导入 jsx
【发布时间】:2016-08-09 05:34:37
【问题描述】:

这个问题与将 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),静态定义它们不起作用。

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

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

<MainComponent ComponentPath="./SystemComponents">

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

<MainComponent ComponentPath="./UserComponents">

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

【问题讨论】:

    标签: reactjs


    【解决方案1】:

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

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

    然后你做:

    import * as Components from "./components"
    

    那么你会使用:

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

    希望这会有所帮助。

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

    【讨论】:

    • 不错!这个解决方案实际上对我们非常有效。我们可以导入所有库(上面示例中的不同路径)并将所需的库作为道具传递。 PS。由于某种原因,我无法从“./comp_a”导出 CompA,必须先导入它们,然后将它们导出到 json 对象中。
    • @mathan 一个班轮导出是 babel stage-1 预设的一部分:export-extensions
    【解决方案2】:

    截至React 16.6.0,我们可以lazy-load components 并按需调用它们。

    路由

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

    views/index.js

    import { lazy } from 'react';
    
    const SomeView = lazy(() => import('./SomeView'));
    const SomeOtherView = lazy(() => import('./SomeOtherView'));
    
    export { SomeView, SomeOtherView };
    

    MyDynamicComponent.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>
    ))}
    

    【讨论】:

    • 谢谢!在您的示例中,我可以将 views/index.js 拆分为单独的 npm 包吗?例如它可以位于另一个 yarn 工作区或 npm 链接包中吗?
    • @mathan 在单独的包中,创建一个包含所需组件名称的数组。然后,您将按如下方式导出该数组:module.exports = myArray。在views/index.js 中导入包并循环导出的数组,将数组值插入到循环输出中。这应该对你有用。
    【解决方案3】:

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

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

    希望这可能会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-30
      • 2020-04-05
      • 1970-01-01
      • 2018-07-17
      • 2015-05-04
      • 2015-07-04
      相关资源
      最近更新 更多