Created
February 19, 2017 17:08
-
-
Save zackify/fce7f7eaa317568ad635d9fbad905886 to your computer and use it in GitHub Desktop.
Async link and route components that wait for the bundle (no route change -> empty content -> bundle loads -> page content is now there)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Link } from 'react-router-dom' | |
import { loadRoute } from './route-helper' | |
export default class AsyncLink extends React.Component { | |
async loadBeforeNavigate (blockPush) { | |
let { to, dataPath } = this.props | |
let { router } = this.context | |
await loadRoute(dataPath || to.substring(1)) | |
if (blockPush) return | |
window.scrollTo(0, 0) | |
return router.push(to) | |
} | |
render () { | |
let { to, onClick, className, onBlockedClick, children } = this.props // eslint-disable-line | |
return ( | |
<Link | |
to={to} | |
className={className} | |
onClick={e => { | |
e.preventDefault() | |
if (onBlockedClick) { | |
this.loadBeforeNavigate(true) | |
return onBlockedClick() | |
} | |
this.loadBeforeNavigate() | |
if (onClick) onClick() | |
}} | |
>{children}</Link> | |
) | |
} | |
} | |
AsyncLink.contextTypes = { | |
router: React.PropTypes.object | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let language = navigator.language.toLowerCase() | |
if (navigator.languages) language = navigator.languages[0].toLowerCase() | |
async function loadComponent (path) { | |
return await System.import(`../../views/${path}`) | |
} | |
export async function loadLanguage (path) { | |
try { | |
return await System.import(`../../sites/${process.env.SITE_FOLDER}/${path}/${language}`) | |
} catch (e) { | |
return await System.import(`../../sites/${process.env.SITE_FOLDER}/${path}/en-us`) | |
} | |
} | |
export async function loadRoute (dataPath) { | |
if (window.components[dataPath]) return {} | |
try { | |
const [ component, text ] = await Promise.all([ | |
loadComponent(dataPath), | |
loadLanguage(dataPath) | |
]) | |
if (component) { | |
window.components[dataPath] = { | |
component: component.default, | |
text: text ? text.default : {} | |
} | |
} | |
return { component, text } | |
} catch (e) { | |
console.warn(`async route: ${dataPath} does not exist`) | |
return {} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Route } from 'react-router-dom' | |
import { loadRoute } from './route-helper' | |
class Async extends React.Component { | |
constructor ({ dataPath, ...props }) { | |
super() | |
if (window.components[dataPath]) this.state = { ...window.components[dataPath] } | |
else this.state = {} | |
} | |
componentDidMount () { | |
this.mounted = true | |
if (!this.state.component) this.load(this.props) | |
} | |
componentWillUnmount () { | |
this.mounted = false | |
} | |
componentWillReceiveProps (props) { | |
if (this.props !== props) this.load(props) | |
} | |
async load ({ dataPath }) { | |
let { component, text } = await loadRoute(dataPath) | |
if (!component) return | |
this.setState({ | |
component: component.default, | |
text: text.default | |
}) | |
} | |
render () { | |
let { component, text } = this.state | |
if (!component || !text) return null | |
return React.createElement(component, { ...this.props, text }) | |
} | |
} | |
const CustomRoute = props => ( | |
<Route | |
{...props} | |
component={Async} | |
/> | |
) | |
export default CustomRoute |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment