Created
September 28, 2016 15:35
-
-
Save henhan/c0cc0b8eaa792d8cc77fae745d718a22 to your computer and use it in GitHub Desktop.
History enabling redux reducer decorator
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
'use strict'; | |
function historyEnable(reducer) { | |
var initObject = { | |
past: [], | |
present: reducer(undefined, {}), | |
future: [] | |
}; | |
// Return a reducer that handles back, forward, and setting history stops | |
return function (state, action) { | |
state = state || initObject; | |
switch (action.type) { | |
case 'GO_BACK': | |
var previousState = state.past[state.past.length - 1]; | |
var newPast = state.past.slice(0, state.past.length - 1); | |
var newFuture = [state.present].concat(state.future); | |
return { | |
past: newPast, | |
present: previousState, | |
future: newFuture | |
}; | |
case 'GO_FORWARD': | |
return { | |
past: [].concat(state.past).concat([state.present]), | |
present: state.future[0], | |
future: state.future.slice(1) | |
}; | |
case 'SET_HISTORY_POINT': | |
return { | |
past: [].concat(state.past).concat([state.present]), | |
present: state.present, | |
future: [] | |
}; | |
default: | |
// Handle an action without affecting history state | |
return { | |
past: state.past, | |
present: reducer(state.present, action), | |
future: state.future | |
}; | |
} | |
}; | |
} | |
module.exports = historyEnable; |
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
'use strict'; | |
var redux = require('redux'); | |
var historyEnable = require('./historyEnable.js'); | |
function reducer(state, action) { | |
state = state === undefined ? 5 : state; | |
switch (action.type) { | |
case 'PLUS': | |
return state + 1; | |
case 'MINUS': | |
return state - 1; | |
default: | |
return state; | |
} | |
} | |
test('initialization of state should work', function() { | |
var store = redux.createStore( | |
historyEnable(reducer) | |
); | |
var state = store.getState(); | |
expect(state).toBeDefined(); | |
expect(state.past).toEqual([]); | |
expect(state.future).toEqual([]); | |
expect(state.present).toEqual(5); | |
}); | |
test('setting history point should work', function() { | |
var store = redux.createStore( | |
historyEnable(reducer) | |
); | |
store.dispatch({ | |
type: 'SET_HISTORY_POINT' | |
}); | |
var state = store.getState(); | |
expect(state.past).toEqual([5]); | |
expect(state.future).toEqual([]); | |
expect(state.present).toEqual(5); | |
}); | |
test('navigating back should work', function() { | |
var store = redux.createStore( | |
historyEnable(reducer) | |
); | |
store.dispatch({ | |
type: 'SET_HISTORY_POINT' | |
}); | |
store.dispatch({ | |
type: 'PLUS' | |
}); | |
store.dispatch({ | |
type: 'SET_HISTORY_POINT' | |
}); | |
store.dispatch({ | |
type: 'PLUS' | |
}); | |
store.dispatch({ | |
type: 'GO_BACK' | |
}); | |
var state = store.getState(); | |
expect(state.past).toEqual([5]); | |
expect(state.future).toEqual([7]); | |
expect(state.present).toEqual(6); | |
}); | |
test('navigating forward should work', function() { | |
var store = redux.createStore( | |
historyEnable(reducer) | |
); | |
store.dispatch({ | |
type: 'SET_HISTORY_POINT' | |
}); | |
store.dispatch({ | |
type: 'PLUS' | |
}); | |
store.dispatch({ | |
type: 'SET_HISTORY_POINT' | |
}); | |
store.dispatch({ | |
type: 'PLUS' | |
}); | |
store.dispatch({ | |
type: 'GO_BACK' | |
}); | |
store.dispatch({ | |
type: 'GO_FORWARD' | |
}); | |
var state = store.getState(); | |
expect(state.past).toEqual([5, 6]); | |
expect(state.future).toEqual([]); | |
expect(state.present).toEqual(7); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment