router: suppress re-render on same state

- views will no longer be re-rendered if the state hasn't changed
- `oldState` is passed as the final argument in a view. E.g. `params,
  state, send, oldState`. This is mostly because it will usually only be
  used for optimizing - changing the order would be a breaking change
  :(
This commit is contained in:
Yoshua Wuyts
2016-05-31 12:30:40 +02:00
parent bd28e93cd1
commit 3153fcb26c
+13 -6
View File
@@ -3,6 +3,7 @@ const sheetRouter = require('sheet-router')
const document = require('global/document') const document = require('global/document')
const href = require('sheet-router/href') const href = require('sheet-router/href')
const sendAction = require('send-action') const sendAction = require('send-action')
const mutate = require('xtend/mutable')
const assert = require('assert') const assert = require('assert')
const xtend = require('xtend') const xtend = require('xtend')
const yo = require('yo-yo') const yo = require('yo-yo')
@@ -118,6 +119,7 @@ function choo () {
function handleAction (action, state, send) { function handleAction (action, state, send) {
var reducersCalled = false var reducersCalled = false
var effectsCalled = false var effectsCalled = false
const newState = xtend(state)
// validate if a namespace exists. Namespaces // validate if a namespace exists. Namespaces
// are delimited by the first ':'. Perhaps // are delimited by the first ':'. Perhaps
@@ -132,9 +134,12 @@ function choo () {
const _reducers = ns ? reducers[ns] : reducers const _reducers = ns ? reducers[ns] : reducers
if (_reducers && _reducers[action.type]) { if (_reducers && _reducers[action.type]) {
if (ns) { if (ns) {
const newState = _reducers[action.type](action, state[ns]) const reducedState = _reducers[action.type](action, state[ns])
state[ns] = xtend(state[ns], newState) if (!newState[ns]) newState[ns] = {}
} else state = xtend(state, reducers[action.type](action, state)) mutate(newState[ns], xtend(state[ns], reducedState))
} else {
mutate(newState, reducers[action.type](action, state))
}
reducersCalled = true reducersCalled = true
} }
@@ -149,14 +154,16 @@ function choo () {
throw new Error('Could not find action ' + action.type) throw new Error('Could not find action ' + action.type)
} }
return state // allows (newState === oldState) checks
return (reducersCalled) ? newState : state
} }
// update the DOM after every state mutation // update the DOM after every state mutation
// (obj, obj) -> null // (obj, obj) -> null
function onchange (action, state) { function onchange (action, newState, oldState) {
if (newState === oldState) return
const oldTree = document.querySelector('#' + rootId) const oldTree = document.querySelector('#' + rootId)
const newTree = _router(state.app.location, state, send) const newTree = _router(newState.app.location, newState, send, oldState)
newTree.setAttribute('id', rootId) newTree.setAttribute('id', rootId)
yo.update(oldTree, newTree) yo.update(oldTree, newTree)
} }