小编典典

动态加载反应组分

reactjs

我需要动态加载React组件。

我从用户获取要加载为字符串的组件名称。我正在使用 webpack

如何动态加载组件,而不要使用静态import语句。似乎Require.Ensure不评估表达式。我想要实现的是这样的事情。

require.ensure([ "./widgets/" + componentName ] ,(require) => {
    let Component = require("./widgets/" + componentName);   
});

但这似乎不起作用。


阅读 237

收藏
2020-07-22

共1个答案

小编典典

基本上,它可以归结为预先创建您将需要的所有块。然后,您只需要一种动态引用它们的方法。这是我基于的解决方案:

http://henleyedition.com/implicit-code-splitting-with-react-router-and-
webpack

这是我不使用React Router的方法(注意:我发现它与redux或动画没有很好的匹配):

//loader:
{
  test: (folder)\/.*\.js,
  include: path.resolve(__dirname, 'src')
  loader: ['lazy?bundle', 'babel']
}

//dynamic usage within React component:
const My_COMPONENTS = {
   ComponentA: require('./folder/ComponentA'),
   ComponentB: require('./folder/ComponentB'),
}

class ParentComponent extends React.Component {
    componentDidMount() {
        My_COMPONENTS[this.props.name](component => this.setState({component}));
    } 
    render() {
       return <this.state.component />;
    }
}

因此,结果是您正在动态渲染组件,但是是从一组静态的预先确定的可能性中进行的-同时,仅向客户端发送的内容不多于访问者实际感兴趣的部分。

另外,这是我做得很好的一个组件:

import React from 'react';
import Modal from './widgets/Modal';

export default class AjaxModal extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.state = {
      Content: null
    };
  }

  componentDidMount() {
    if(this.props.show) {
      this.loadContent();
    }
  }

  componentWillReceiveProps({show}) {
    if(show && !this.state.Content) {
      this.loadContent(1200); //dont interfere with animation
    }
  }

  loadContent(ms=0) {
    setTimeout(() => {
      this.props.requestLazyBundle(({default: Content}) => {
        this.setState({Content});
      });
    }, ms);
  }

  render() {
    let {Content} = this.state;

    return (
      <Modal title={this.props.title} {...this.props} loading={!Content}>
        {Content ? <Content /> : null}
      </Modal>
    );
  }
}

通过传递async require bundler函数this.props.requestLazybundle,如下所示:

render() {

  let requestLazyBundle = require('bundle?lazy&name=AnotherComponent!../content/AnotherComponent');

  return (
    <AjaxModal title='Component Name' {...props} requestLazyBundle={requestLazyBundle} />
  );
}
2020-07-22