Dynamic loading of reactive components

I need to dynamically load a react component.

I get the name of the component to load as a string from the user. I am using webpack.

How to load a component dynamically instead of a static import statement. Require.Ensure does not seem to evaluate expressions. I want to achieve something similar.

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

But that does not work.

+7
reactjs webpack
source share
2 answers

Basically it comes down to pre-creating all the pieces you will ever need. Then you just need a way to dynamically reference them. Here's a solution based on mine:

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

and here is what I am doing as I am not using React Router (side note: I don't think this is a good match for reduction or animation):

 //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 />; } } 

So, the result is that you are dynamically representing the component, but from the static predefined set of features - all the time, only sending more to the client than the pieces that the visitor is actually interested in.

ALSO, here is the component that I have:

 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> ); } } 

pass pass async so that the bundler function runs like this.props.requestLazybundle , for example:

 render() { let requestLazyBundle = require('bundle?lazy&name=AnotherComponent!../content/AnotherComponent'); return ( <AjaxModal title='Component Name' {...props} requestLazyBundle={requestLazyBundle} /> ); } 
+6
source share

Please look at this main page that I have provided for the full source code https://gist.github.com/SamanShafigh/a0fbc2483e75dc4d6f82ca534a6174d4

So, suppose you have 4 components called D1, D2, D3. You need to create a dependency injection and a dependency container mechanism. This is a very simple implementation.

Imagine you have a configuration file that defines your components.

 export default [ { name:'D1', path:'D1' }, { name:'D2', path:'D2' }, { name:'D3', path:'D3' }]; 

Then you may have a component container similar to this

 import componentsConfig from 'ComponentsConfig'; let components = {}; for (var i = 0; i < componentsConfig.length; i++) { let componentConfig = componentsConfig[i]; // Check if component is not already loaded then load it if (components[componentConfig.name] === undefined) { components[componentConfig.name] = require(`${componentConfig.path}`).default; } } export default components; 

Finally, in the place where you want to load your components, you can use your component container to load components dynamically or, in other words, you can insert your components

 import React, { Component } from 'react'; import ComponentContainer from './ComponentContainer'; class App extends Component { render() { let components = ['D1', 'D2', 'D3']; return ( <div> <h2>Dynamic Components Loading</h2> {components.map((componentId) => { let Component = ComponentContainer[componentId]; return <Component>{componentId}</Component>; })} </div> ); } } export default App; 
+2
source share

All Articles