Skip to content

Instantly share code, notes, and snippets.

@nodew
Created March 29, 2017 13:15
Show Gist options
  • Save nodew/b12c9e425c13da5127d1e7f21b607393 to your computer and use it in GitHub Desktop.
Save nodew/b12c9e425c13da5127d1e7f21b607393 to your computer and use it in GitHub Desktop.
a simple redux, just has `createStore` and `combineReducer` method
/*
* demo reducer
* function demoReducer(state, action) {
* do something
* return state;
* }
*
* demo action
* {
* type: [type symbol]
* ...
* }
* */
function createStore(reducer, preloadState) {
let currentState = preloadState
const actionTypes = {
INIT: Symbol()
}
function dispatch(action) {
if (typeof action !== 'object') {
throw new Error('action should be an object')
}
if(action.type === undefined) {
throw new Error('action type is undefined')
}
currentState = reducer(currentState, action)
}
function getState() {
return currentState
}
dispatch({ type: actionTypes.INIT })
return {
getState,
dispatch
}
}
function combineReducer(reducers) {
const reducerKeys = Object.keys(reducers)
const finalReducers = {}
/*
* filter reducer isn't function
* */
for (let i = 0; i < reducerKeys.length; i++) {
const key = reducerKeys[i]
if (typeof reducers[key] === 'function') {
finalReducers[key] = reducers[key]
}
}
const finalReducerKeys = Object.keys(finalReducers)
return function combination(state = {}, action) {
const nextState = {}
let hasChanged = false
for (let i = 0; i< finalReducerKeys.length; i++) {
const key = finalReducerKeys[i]
const reducer = finalReducers[key]
const previousStateForKey = state[key]
const nextStateForKey = reducer(previousStateForKey, action)
nextState[key] = nextStateForKey
hasChanged = hasChanged || nextStateForKey !== previousStateForKey
}
return hasChanged ? nextState : state
}
}
// ------------------------ test --------------------------
const actionTypes = {
add: Symbol(),
minus: Symbol(),
updateA: Symbol(),
updateB: Symbol()
}
const reducer = (state, action) => {
switch (action.type) {
case actionTypes.add:
return state + action.value
case actionTypes.minus:
return state - action.value
default:
return state
}
}
var store = createStore(reducer, 0)
console.log(store.getState())
store.dispatch({
type: actionTypes.add,
value: 3
})
console.log(store.getState())
store.dispatch({
type: actionTypes.minus,
value: 1
})
console.log(store.getState())
// ------------------- test combine reducer --------------------
const stateA = (state = 0, action) => {
switch(action.type) {
case actionTypes.updateA:
return action.value
default:
return state
}
}
const stateB = (state = 2, action) => {
switch(action.type) {
case actionTypes.updateB:
return action.value
default:
return state
}
}
const reducers = combineReducer({
stateA,
stateB
})
const storeB = createStore(reducers)
console.log(storeB.getState())
storeB.dispatch({
type: actionTypes.updateA,
value: 21
})
storeB.dispatch({
type: actionTypes.updateB,
value: 12
})
console.log(storeB.getState())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment