0

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

元数据.json:

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

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

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

export default createFirstLayer;

我做了一些研究并确定了 @loadable/component 包。使用这个包 as 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。如何加载函数?

我也尝试过惰性方法。

我在这里重新创建了我的问题的工作演示。

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

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

这会导致 TypeError 未处理拒绝(错误):找不到模块 './createFirstLayer.js'。(匿名函数) src/components lazy /^.*$/ groupOptions: {} namespace object:66

我也尝试过

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

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

4

1 回答 1

2

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

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

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

像这样:

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;

这是工作示例

于 2021-03-09T01:40:16.873 回答