Created
October 28, 2016 15:36
-
-
Save danieldunderfelt/f7e333f20c13a6b03431d2e1019f224d to your computer and use it in GitHub Desktop.
next.js global store that persists between routes
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
/** | |
* PROBLEM: | |
* In next.js, each route points to a distinct top-level component. | |
* Since there is no higher-level components in next.js, how to have | |
* a store that persists between route changes is not immediately | |
* obvious. One solution is this: a higher-order component that you | |
* wrap each of your top-level route components with. | |
* | |
* This is borrowed from next.js' Redux example from here: | |
* https://github.com/zeit/next.js/wiki/Redux-example | |
* | |
* Using `window` works, but it does initially feel icky. Maybe | |
* there is a better way, or next.js needs to support a level of | |
* components higher than the route components. | |
* | |
* PS. This example uses my `mobx-app` package: | |
* https://github.com/danieldunderfelt/mobx-app | |
**/ | |
import React, { Component, PropTypes } from 'react' | |
import { observer, Provider } from 'mobx-react' | |
import { createStore } from 'mobx-app' | |
import store from './store' | |
const stores = { | |
Store: store | |
} | |
function initStore( initialState = {}, isServer ) { | |
if( isServer && typeof window === 'undefined' ) { | |
return createStore( stores, initialState ) | |
} else { | |
if( !window.store ) { | |
window.store = createStore( stores, initialState ) | |
} | |
return window.store | |
} | |
} | |
export default Component => { | |
return observer(class extends Component { | |
static getInitialProps({ req }) { | |
const isServer = !!req | |
const store = initStore( {}, isServer ) | |
return { initialState: store.state, isServer } | |
} | |
constructor(props) { | |
super(props) | |
const { initialState, isServer } = props | |
this.store = initStore(initialState, isServer) | |
} | |
render() { | |
const { props } = this | |
const { state, actions } = this.store | |
return ( | |
<Provider state={ state } actions={ actions }> | |
<Component { ...props } /> | |
</Provider> | |
) | |
} | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment