1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

examples/with-mobx : Fix and simplify (#5537)

I spent far too much time fiddling with this example project before realizing it contained a bug in the store initialization logic and it was a bit more complex than it needed to be.

* The custom server was not needed
* The store-initialization did effectively the same thing twice for no reason
* And wrapping MyApp component in a HOC was wholly unnecessary indirection

My changes are split into four discrete commits for clarity.
This commit is contained in:
Már Örlygsson 2018-11-06 09:18:26 +00:00 committed by Tim Neutkens
parent a09ca535c3
commit 420f74c867
5 changed files with 50 additions and 97 deletions

View file

@ -1,50 +0,0 @@
import React from 'react'
import {initializeStore} from '../store'
const isServer = typeof window === 'undefined'
const __NEXT_MOBX_STORE__ = '__NEXT_MOBX_STORE__'
function getOrCreateStore(initialState) {
// Always make a new store if server, otherwise state is shared between requests
if (isServer) {
return initializeStore(initialState)
}
// Create store if unavailable on the client and set it on the window object
if (!window[__NEXT_MOBX_STORE__]) {
window[__NEXT_MOBX_STORE__] = initializeStore(initialState)
}
return window[__NEXT_MOBX_STORE__]
}
export default (App) => {
return class AppWithMobx extends React.Component {
static async getInitialProps (appContext) {
// Get or Create the store with `undefined` as initialState
// This allows you to set a custom default initialState
const mobxStore = getOrCreateStore()
// Provide the store to getInitialProps of pages
appContext.ctx.mobxStore = mobxStore
let appProps = {}
if (typeof App.getInitialProps === 'function') {
appProps = await App.getInitialProps.call(App, appContext)
}
return {
...appProps,
initialMobxState: mobxStore
}
}
constructor(props) {
super(props)
this.mobxStore = getOrCreateStore(props.initialMobxState)
}
render() {
return <App {...this.props} mobxStore={this.mobxStore} />
}
}
}

View file

@ -2,9 +2,9 @@
"name": "with-mobx",
"version": "1.0.0",
"scripts": {
"dev": "node server.js",
"dev": "next",
"build": "next build",
"start": "NODE_ENV=production node server.js"
"start": "next start"
},
"dependencies": {
"mobx": "^2.7.0",

View file

@ -1,19 +1,38 @@
import App, {Container} from 'next/app'
import React from 'react'
import withMobxStore from '../lib/with-mobx-store'
import { initializeStore } from '../store'
import { Provider } from 'mobx-react'
class MyApp extends App {
render () {
const {Component, pageProps, mobxStore} = this.props
return (
<Container>
<Provider store={mobxStore}>
<Component {...pageProps} />
</Provider>
</Container>
)
}
}
class MyMobxApp extends App {
static async getInitialProps(appContext) {
// Get or Create the store with `undefined` as initialState
// This allows you to set a custom default initialState
const mobxStore = initializeStore()
// Provide the store to getInitialProps of pages
appContext.ctx.mobxStore = mobxStore
export default withMobxStore(MyApp)
let appProps = await App.getInitialProps(appContext)
return {
...appProps,
initialMobxState: mobxStore
};
}
constructor(props) {
super(props)
this.mobxStore = initializeStore(props.initialMobxState)
}
render() {
const { Component, pageProps } = this.props
return (
<Container>
<Provider store={this.mobxStore}>
<Component {...pageProps} />
</Provider>
</Container>
);
}
}
export default MyMobxApp

View file

@ -1,21 +0,0 @@
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const { createServer } = require('http')
const { parse } = require('url')
const next = require('next')
const mobxReact = require('mobx-react')
const app = next({ dev })
const handle = app.getRequestHandler()
mobxReact.useStaticRendering(true)
app.prepare().then(() => {
createServer((req, res) => {
const parsedUrl = parse(req.url, true)
handle(req, res, parsedUrl)
}).listen(port, err => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})

View file

@ -1,13 +1,16 @@
import { action, observable } from 'mobx'
import { useStaticRendering } from 'mobx-react'
let store = null
const isServer = typeof window === 'undefined'
useStaticRendering(isServer)
class Store {
@observable lastUpdate = 0
@observable light = false
constructor (isServer, lastUpdate) {
this.lastUpdate = lastUpdate
constructor (isServer, initialData = {}) {
this.lastUpdate = initialData.lastUpdate != null ? initialData.lastUpdate : Date.now()
this.light = !!initialData.light
}
@action start = () => {
@ -20,13 +23,15 @@ class Store {
stop = () => clearInterval(this.timer)
}
export function initializeStore (isServer, lastUpdate = Date.now()) {
let store = null
export function initializeStore (initialData) {
// Always make a new store if server, otherwise state is shared between requests
if (isServer) {
return new Store(isServer, lastUpdate)
} else {
if (store === null) {
store = new Store(isServer, lastUpdate)
}
return store
return new Store(isServer, initialData)
}
if (store === null) {
store = new Store(isServer, initialData)
}
return store
}