Created
October 23, 2017 15:37
-
-
Save sergeysova/dde2522bc52b22b7a1cb487a6da44c9d to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| const actName = (ns, nm) => ns ? `${ns}/${nm}` : nm | |
| function createActionTypes(namespace, namelist) { | |
| if (Array.isArray(namespace)) { | |
| namelist = namespace | |
| namespace = false | |
| } | |
| return namelist.reduce((map, name) => | |
| Object.assign(map, { | |
| [name]: actName(namespace, name) | |
| }), | |
| {} | |
| ) | |
| } | |
| const pass = (obj) => obj | |
| const empty = () => null | |
| function createActions(namespace, actionsMap) { | |
| return Object.keys(actionsMap).reduce((map, name) => { | |
| const actionFn = actionsMap[name] | |
| const type = actName(namespace, name) | |
| const actionCreator = (...args) => ({ | |
| type, | |
| payload: actionFn(...args) | |
| }) | |
| actionCreator.type = type | |
| return Object.assign(map, { [name]: actionCreator }) | |
| }, {}) | |
| } | |
| class Action { | |
| constructor() { | |
| this.effects = [] | |
| } | |
| map(fn) { | |
| this.effects.push({ type: 'map', fn }) | |
| return this | |
| } | |
| update(fn) { | |
| this.effects.push({ type: 'update', fn }) | |
| return this | |
| } | |
| build() { | |
| return (state, action) => { | |
| let value = action.payload | |
| for (const effect of this.effects) { | |
| switch (effect.type) { | |
| case 'map': | |
| value = effect.fn(value) | |
| break; | |
| case 'update': { | |
| return effect.fn(value, state) | |
| } | |
| } | |
| } | |
| return value | |
| } | |
| } | |
| } | |
| function action() { | |
| return new Action | |
| } | |
| function reducer(initial) { | |
| const actionsMap = {} | |
| function realReducer(state, action) { | |
| if (actionsMap[action.type]) { | |
| return actionsMap[action.type](state, action) | |
| } | |
| return initial | |
| } | |
| realReducer.of = (actionType, action) => { | |
| actionsMap[actionType.type || actionType] = action.build() | |
| return realReducer | |
| } | |
| return realReducer | |
| } | |
| // ===== USAGE ===== // | |
| const Types = createActionTypes('foo', ['baz', 'baf']) | |
| console.log(Types) | |
| const Actions = createActions('profile', { | |
| reset: empty, | |
| setName: (name) => ({ name }), | |
| update: pass, | |
| }) | |
| console.log(Actions.reset()) | |
| console.log(Actions.setName('Sova')) | |
| console.log(Actions.update({ foo: 'bar' })) | |
| const red = reducer({ first: '', last: '' }) | |
| .of( | |
| Actions.setName, | |
| action() | |
| .map(({ name }) => name.split(' ')) | |
| .update(([first, last], state) => ({ ...state, first, last })) | |
| ) | |
| console.log(red({}, Actions.setName('Sergey Sova'))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment