简体   繁体   English

在 React 中使用 @loadable/component 从外部脚本加载 function

[英]Load function from external script using @loadable/component in React

I have a JSON file with several filepaths to scripts that I want to be able to load dynamically into my React app, to build each component based on specifications that are in the metadata.我有一个 JSON 文件,其中包含多个脚本文件路径,我希望能够动态加载到我的 React 应用程序中,以根据元数据中的规范构建每个组件。 Currently I have the metadata in my app as a Metadata data object.目前,我的应用程序中有元数据作为Metadata数据数据 object。

metadata.json:元数据.json:

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

Each script exports a function that I want to be able to use to construct the component.每个脚本都导出一个 function,我希望能够使用它来构建组件。 For troubleshooting purposes, it currently only returns a simple message.出于故障排除的目的,它目前只返回一条简单的消息。

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

export default createFirstLayer;

I did some research and identified the @loadable/component package.我做了一些研究并确定了@loadable/component package。 Using this package as import loadable from "@loadable/component";使用此 package 作为import loadable from "@loadable/component"; , I attempted to load my script into App.js like this: ,我试图将我的脚本加载到 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);
    });
  }

Everything I have tried throws the TypeError createLayer is not a function .我尝试过的一切都会抛出 TypeError createLayer is not a function How can I get the function loaded?如何加载 function?

I have also attempted the lazy method.我也尝试过惰性方法。

I have recreated a working demo of my problem here .我在这里重新创建了我的问题的工作演示。

EDIT: I have tried to put this at the top of my app编辑:我试图把它放在我的应用程序的顶部

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

This causes the TypeError Unhandled Rejection (Error): Cannot find module './createFirstLayer.js'.这会导致 TypeError 未处理拒绝(错误):找不到模块 './createFirstLayer.js'。 (anonymous function) src/components lazy /^.*$/ groupOptions: {} namespace object:66 (匿名函数) src/components lazy /^.*$/ groupOptions: {} namespace object:66

I have also attempted我也尝试过

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

My goal is to be able to call the appropriate function to create particular layer, and match them up in the metadata.我的目标是能够调用适当的 function 来创建特定层,并在元数据中匹配它们。

You don't need @loadable/component for two reasons.您不需要@loadable/component有两个原因。

  1. You can accomplish your goal with dynamic imports您可以通过动态导入来实现您的目标
  2. '@loadable/component' returns a React Component object, not your function. '@loadable/component' 返回一个 React 组件 object,而不是你的 function。

To use dynamic imports simply parse your JSON the way you were, but push the call to the import's default function into state .要使用动态导入,只需按照您原来的方式解析您的 JSON,但将对导入的默认 function 的调用推送到state中。 Then all you have to do is render the " layers " from within the state.然后您所要做的就是从 state 中渲染“”。

Like this:像这样:

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;

Here is the working example这是工作示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM