【问题标题】:Load function from external script using @loadable/component in React在 React 中使用 @loadable/component 从外部脚本加载函数
【发布时间】:2021-06-06 20:47:36
【问题描述】:

我有一个 JSON 文件,其中包含多个脚本文件路径,我希望能够将这些脚本动态加载到我的 React 应用程序中,以根据元数据中的规范构建每个组件。目前,我的应用程序中的元数据作为 Metadata 数据对象。

元数据.json:

{
  "component1": { "script": "./createFirstLayer.js" },
  "component2": { "script": "./createSecondLayer.js" }
}

每个脚本都导出一个我希望能够用来构造组件的函数。出于故障排除的目的,它目前只返回一条简单的消息。

function createFirstLayer(name) {
  return name + " loaded!";
}

export default createFirstLayer;

我做了一些研究并确定了@loadable/component 包。使用这个包作为import loadable from "@loadable/component";,我尝试将我的脚本加载到 App.js 中,如下所示:

  async componentDidMount() {
    Object.keys(Metadata).forEach(function(name) {
      console.log(Metadata[name].script);
      var createLayer = loadable(() => import(Metadata[name].script));
      var message = createLayer(name);
      console.log(message);
    });
  }

我尝试过的所有操作都会引发 TypeError createLayer is not a function。如何加载函数?

我也尝试过lazy 方法。

我重新创建了我的问题 here 的工作演示。

编辑:我试图把它放在我的应用程序的顶部

const scripts = {};
Object.keys(Metadata).forEach(async function(name) {
    import(Metadata[name].script).then((cb) => scripts[name] = cb);
});

这会导致 TypeError Unhandled Rejection (Error): Cannot find module './createFirstLayer.js'。 (匿名函数) src/components 懒惰 /^.*$/ groupOptions: {} namespace object:66

我也试过

const scripts = {};
Object.keys(Metadata).forEach(async function(name) {
    React.lazy(() => import(Metadata[name].script).then((cb) => scripts[name] = cb));
});

我的目标是能够调用适当的函数来创建特定层,并在元数据中匹配它们。

【问题讨论】:

    标签: javascript reactjs dynamic loadable-component


    【解决方案1】:

    您不需要@loadable/component 有两个原因。

    1. 您可以通过动态导入实现您的目标
    2. '@loadable/component' 返回一个 React 组件对象,而不是你的函数。

    要使用动态导入,只需按照原来的方式解析 JSON,但将对导入的默认函数的调用推送到 state。然后你所要做的就是从状态中渲染“layers”。

    像这样:

    import React, { Component } from "react";
    import Metadata from "./metadata.json";
    
    class App extends Component {
      constructor(props) {
        super(props);
        this.state = { messages: [] };
      }
      async componentDidMount() {
        Object.keys(Metadata).forEach(name=> import(`${Metadata[name].script}`).then(cb =>
          this.setState((state, props) => ({ messages: [...state.messages, cb.default(cb.default.name)] }))));
      }
      render() {
        return (
          <div className="App">
            {this.state.messages.map((m, idx) => (
              <h1 key={idx}>{m}</h1>
            ))}
          </div>
        );
      }
    }
    
    export default App;
    

    这里是the working example

    【讨论】:

    • 谢谢!我正在更仔细地查看这个,因为我似乎无法在 componentDidMount 中打印消息
    • 是的 - 存在竞争条件。这确实有效,让我修复它。但我会隐藏这个答案,直到它正常工作。
    • 我根据您的回答尝试更新了我的问题
    • 这很奇怪...我将在读取的 IDE 中查看而不是 repl 的东西。
    • 好的,这是将图层渲染到视图中的整个解决方案。不得不将解析移回componentDidMount() 以克服竞争条件。还要注意,我必须使用模板文字字符串作为变量组件名称。但这现在按预期工作。很抱歉混淆了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-17
    • 1970-01-01
    • 2020-06-05
    • 2017-03-29
    • 1970-01-01
    • 1970-01-01
    • 2016-10-14
    相关资源
    最近更新 更多