import React from 'react' let firstRoute = true; export default (getComponent) => class AsyncComponent extends React.Component { static Component = null; mounted = false; // Remembers scroll positions based on location->key static scrollPositions = {}; state = { Component: AsyncComponent.Component }; componentDidMount() { this.mounted = true; if ( AsyncComponent.Component === null ) { getComponent().then((m) => m.default).then((Component) => { if ( firstRoute ) { // We want to handle scroll restoration on our own from now on if ( 'scrollRestoration' in window.history ) { window.history.scrollRestoration = 'manual'; } firstRoute = false; } AsyncComponent.Component = Component; if ( this.mounted ) { this.setState({Component}); } }) } else { const {action, location:{key="root"}} = this.props; // POP means user is going forward or backward in history, restore previous scroll position if ( action === 'POP' ) { const pos = AsyncComponent.scrollPositions[key]; if ( pos ) { scroll(pos[0], pos[1]); return; } } } // Scroll to top of viewport scroll(0,0); } componentWillUnmount() { // Remember scroll position so we can restore if we return to this view via browser history const {location:{key="root"}} = this.props; AsyncComponent.scrollPositions[key] = [window.pageXOffset, window.pageYOffset]; this.mounted = false; } render() { const {Component} = this.state; return Component === null ?