<div id="root"></div>
// this is just here to display results to DOM
const addResultToDOM = (...args) => $('#root').append(`<div>${args.join(' ')}</div>`)
const compose = (...fns) => arg => fns.reduce((acc, fn) => fn(acc), arg)
const curry = (uncurriedFn, ...args) => {
// you can get the arity of a function by calling length on the fn
const arity = uncurriedFn.length
const accumulator = (...accArgs) => {
let argsCopy = [...args] //
if (accArgs.length > 0) {
argsCopy = [...argsCopy, ...accArgs]
}
if (args.length >= arity) return uncurriedFn.apply(null, argsCopy)
return curry.apply(null, [uncurriedFn, ...argsCopy]) // recurse
}
// if any args passed in, pass them to the accumulator
return args.length >= arity ? accumulator() : accumulator
}
const initialState = { counter: 0, timesClicked: 0 }
const set = curry((key, value, obj) => Object.assign({}, obj, { [key]: value }))
const counterReducer = (state = initialState, action = {}) => {
switch (action.type) {
case 'INCREMENT': {
const { counter, timesClicked } = state
return compose(
set('counter', counter + 1),
set('timesClicked', timesClicked + 1),
)(state)
}
case 'DECREMENT': {
const { counter, timesClicked } = state
return compose(
set('counter', counter - 1),
set('timesClicked', timesClicked + 1),
)(state)
}
default:
return state
}
}
const state0 = counterReducer()
addResultToDOM('state0', JSON.stringify(state0, null, 2))
const state1 = counterReducer(state0)
addResultToDOM('state1', JSON.stringify(state1, null, 2))
const state2 = counterReducer(state1, { type: 'INCREMENT' })
addResultToDOM('state2', JSON.stringify(state2, null, 2))
const fakeState = counterReducer(state1, { type: 'INCREMENT' })
addResultToDOM('fakeState', JSON.stringify(fakeState, null, 2))
const state3 = counterReducer(state2, { type: 'INCREMENT' })
addResultToDOM('state3', JSON.stringify(state3, null, 2))
const state4 = counterReducer(state3, { type: 'DECREMENT' })
addResultToDOM('state4', JSON.stringify(state4, null, 2))
const anotherFakeState = counterReducer(state3, { type: 'DECREMENT' })
addResultToDOM('anotherFakeState', JSON.stringify(anotherFakeState, null, 2))
const state1Branch = counterReducer(state1, { type: 'DECREMENT' })
addResultToDOM('state1Branch', JSON.stringify(state1Branch, null, 2))
initialState
addResultToDOM('initialState', JSON.stringify(initialState, null, 2))
This Pen doesn't use any external CSS resources.