简体   繁体   English

在状态内部动态加载反应组件

[英]Dynamic loading of react components inside state

I have a really interesting problem at hand. 我手头有一个非常有趣的问题。

I am currently working on a Admin-Interface for a headless CMS and I want to dynamically load the components for viewing the content of different parts. 我目前正在为无头CMS设计Admin-Interface,并且我想动态加载组件以查看不同部分的内容。

I know that it is rather easy to accomplish wit React Router since v4, but I don't want to rely on Routes to handle this to keep the URL as clean as possible. 我知道从v4开始使用React Router相当容易,但是我不想依靠Routes来处理它以保持URL尽可能干净。

Here is what I am trying to do: 这是我正在尝试做的事情:

  1. I want to render the basic layout of the UI (in which I load the different sub-components when clicking the navigation-links) 我想呈现UI的基本布局(在其中单击导航链接时加载不同的子组件)
  2. Inside the async componentWillMount() function of this basic layout I want to import() said components using await import() 在这个基本布局的async componentWillMount()函数内部,我想使用await import()import()所述组件
  3. Ideally those should be stored to the state inside a property called this.state.mainComponents 理想情况下,应将其存储到状态为this.state.mainComponents的状态中。
  4. I will then pass down the names of the components to the navigation component along with a function which will change the currently displayed component in the parents state 然后,我将把这些组件的名称和一个函数一起传递给导航组件,该函数将更改父state当前显示的组件

I tried several different approaches, but did not manage to get it to work until now. 我尝试了几种不同的方法,但直到现在一直没有使它起作用。

This is what I have now: 这就是我现在所拥有的:

  async componentDidMount() {
    const mainComponents = {
      Dashboard: await import('../_mainComponents/Dashboard').then(
        ({ Dashboard }) => {
          return Dashboard;
        },
      ),
    };

    const componentNames = [];

    for (let p in mainComponents) {
      componentNames.push(p);
    }

    this.setState({
      mainComponents: {
        views: mainComponents,
        names: componentNames,
      },
      currentComponent: mainComponents.Dashboard,
      currentTitle: 'Dashboard',
    });
  }

I would really appreciate any help you could give me on this. 我真的很感谢您可以为此提供的任何帮助。

EDIT: 编辑:

So according to the answer of @Mosè Raguzzini I implemented react-loadable again and tried to store the const inside my state like this: 因此,根据@MosèRaguzzini的回答,我再次实现了react-loadable ,并尝试将const存储在我的状态中,如下所示:

const LoadableDashboard = Loadable({
  loader: () => import('../_mainComponents/Dashboard'),
  loading: Loading
});

const mainComponents = {
  Dashboard: LoadableDashboard
};

And inside my constructor function I am trying to pass this Object into the state like this: 在我的构造函数中,我试图将此对象传递给这样的状态:

const componentNames = [];

for (let p in mainComponents) {
  componentNames.push(p);
}

this.state = {
  mainComponents: {
    views: mainComponents,
    names: componentNames,
  },
  currentComponent: null,
  currentTitle: null,
  loading: false,
};

It is not working when trying to output the Components stored inside the this.state.mainComponents.views object inside to the render function. 尝试将存储在this.state.mainComponents.views对象内部的组件输出到render函数时,此方法不起作用。

When using <Dashboard /> it is working as expected, but this is not what I am trying to accomplish here since I don't want to add every component to the render function in a massive switch ... case . 当使用<Dashboard />它可以按预期工作,但这不是我想要在这里完成的工作,因为我不想在大量的switch ... case中将每个组件添加到render函数中。

Does anybody of you have an idea how I can accomplish this? 你们中有人知道我该如何做到吗?

I found a solution to my problem and wanted to share it with all of those who will come after me searching for an appropiate answer. 我找到了解决问题的方法,并希望与所有寻求我找到合适答案的人分享。

Here is what I did: 这是我所做的:

import Loadable from 'react-loadable';
import Loading from '../_helperComponents/Loading';

// Define the async-loadable components here and store them inside of the mainComponent object
const LoadableDashboard = Loadable({
  loader: () => import('../_mainComponents/Dashboard'),
  loading: Loading,
});

const LoadableUserOverview = Loadable({
  loader: () => import('../_mainComponents/UserOverview'),
  loading: Loading,
});

const mainComponents = {
  Dashboard: <LoadableDashboard />,
  User: <LoadableUserOverview />,
};

I do not store the components inside my state (it would have been possible but goes against the guidelines as I've found out by researching state even further) :D 我没有将组件存储在我的状态内(这是可能的,但是违反了我进一步研究状态所发现的准则):D

With this object I can simply call the corresponding component by outputting it in the render() function like this: 有了这个对象,我可以像下面这样简单地通过在render()函数中输出相应的组件来调用它:

render() {
  return (
    <div>
      {mainComponents[this.state.currentComponent]}
    </div>
  );
}

I hope I could help someone with this. 我希望我可以帮助某人。 Happy coding! 编码愉快!

I suggest to take a look to react-loadable: 我建议看一下react-loadable:

import Loadable from 'react-loadable';
import Loading from './my-loading-component';

const LoadableComponent = Loadable({
  loader: () => import('./my-component'),
  loading: Loading,
});

export default class App extends React.Component {
  render() {
    return <LoadableComponent/>;
  }
}

It provides the feature you need in a clean style. 它以简洁的样式提供您需要的功能。

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

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