Skip to content

Instantly share code, notes, and snippets.

@vbguard
Forked from apostolos/asyncRoute.js
Created March 13, 2020 21:21
Show Gist options
  • Save vbguard/ef5b2e1b0411d0e327c5bf946e09d44e to your computer and use it in GitHub Desktop.
Save vbguard/ef5b2e1b0411d0e327c5bf946e09d44e to your computer and use it in GitHub Desktop.
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
? <div>Loading...</div>
: <Component {...this.props} />;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment