Lazily Load Code Declaratively in React + Webpack

October 5, 2016 ยท View on GitHub

import React from 'react';

const toPromise = (load) => (new Promise((resolve) => ( load(resolve) )));

class LazilyLoad extends React.Component {

constructor() { super(...arguments); this.state = { isLoaded: false, }; }

componentWillMount() { this.load(this.props); }

componentDidMount() { this._isMounted = true; }

componentWillReceiveProps(next) { if (next.modules === this.props.modules) return null; this.load(next); }

componentWillUnmount() { this._isMounted = false; }

load(props) { this.setState({ isLoaded: false, });

const { modules } = props;
const keys = Object.keys(modules);

Promise.all(keys.map((key) => toPromise(modules[key])))
  .then((values) => (keys.reduce((agg, key, index) => {
    agg[key] = values[index];
    return agg;
  }, {})))
  .then((result) => {
    if (!this._isMounted) return null;
    this.setState({ modules: result, isLoaded: true });
  });

}

render() { if (!this.state.isLoaded) return null; return React.Children.only(this.props.children(this.state.modules)); } }

LazilyLoad.propTypes = { children: React.PropTypes.func.isRequired, };

export const LazilyLoadFactory = (Component, modules) => { return (props) => ( {(mods) => <Component {...mods} {...props} />} ); };

export const importLazy = (fetch) => (cb) => ( fetch((mod) => cb(mod.default)) );

export default LazilyLoad;