Skip to content

Instantly share code, notes, and snippets.

@selfcontained
Last active May 26, 2017 16:40
Show Gist options
  • Save selfcontained/808273e2d7fb570cd853919ba966fbf6 to your computer and use it in GitHub Desktop.
Save selfcontained/808273e2d7fb570cd853919ba966fbf6 to your computer and use it in GitHub Desktop.
Lazy Load React component pattern
import React from 'react'
class LazyLoad extends React.Component {
constructor () {
super(...arguments)
this.state = {
isLoaded: false
}
}
componentDidMount () {
this._isMounted = true
this.load()
}
componentDidUpdate (previous) {
const shouldLoad = !!Object.keys(this.props.modules).filter((key) => {
return this.props.modules[key] !== previous.modules[key]
}).length
if (shouldLoad) {
this.load()
}
}
componentWillUnmount () {
this._isMounted = false
}
load () {
this.setState({
isLoaded: false
})
const { modules } = this.props
const keys = Object.keys(modules)
Promise.all(keys.map((key) => 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 () {
let {EmptyState} = this.props
if (!this.state.isLoaded) return EmptyState ? <EmptyState {...this.props} /> : null
return React.Children.only(this.props.children(this.state.modules))
}
}
export const LazyLoadFactory = (Component, modules, EmptyState) => {
return (props) => (
<LazyLoad modules={modules} EmptyState={EmptyState}>
{(mods) => <Component {...mods} {...props} />}
</LazyLoad>
)
}
export default LazyLoad
import React from 'react'
import {LazyLoadFactory} from 'components/lazy-load/'
class LazyLoadedThingy extends React.PureComponent {
render () {
let {Component} = this.props
return (
<Component.default {...this.props} />
)
}
}
function Placeholder (props) {
return (
<div className='loading'>Loading...</div>
)
}
export default LazyLoadFactory(LazyLoadedThingy, {
// path to the component we want to load lazily and keep in it's own bundle
Component: () => System.import(/* webpackChunkName: "thingy" */'./thingy')
}, Placeholder)
import React from 'react'
class Thingy extends React.PureComponent {
render () {
return (
<div>
<p>Do some really heavy things in here and include all sorts of things we don't want loaded by default</p>
</div>
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment