Skip to content

Instantly share code, notes, and snippets.

@sebbdk
Last active February 20, 2020 23:54
Show Gist options
  • Save sebbdk/04bbee348b38ee357b4043e7aace9a9e to your computer and use it in GitHub Desktop.
Save sebbdk/04bbee348b38ee357b4043e7aace9a9e to your computer and use it in GitHub Desktop.
List redux reducer creator
This can be used to bootsrap making reducers that only have to manage an array of data.
// crud-lib.js
import nanoid from 'nanoid';
export function createActionTypes(reducerAlias) {
return {
add: Symbol(`CUD add in ${reducerAlias}`),
remove: Symbol(`CUD remove in ${reducerAlias}`),
update: Symbol(`CUD remove in ${reducerAlias}`),
replace: Symbol(`CUD replace in ${reducerAlias}`)
};
}
export function createDispatchers(actionTypes) {
return {
add: (item) => ({ type: actionTypes.add, item }),
remove: (item) => ({ type: actionTypes.remove, item }),
update: (item) => ({ type: actionTypes.update, item }),
replace: (item) => ({ type: actionTypes.replace, item }),
}
}
export function createActions(types, key = 'id') {
return {
[types.add]: (state, action) => ([ ...state, { id: nanoid(), ...action.item}]),
[types.remove]: (state, action) => state.filter(i => i[key] !== action.item[key]),
[types.update]: (state, action) => state.map(i => {
return i[key] === action.item[key]
? { ...i, ...action.item }
: i;
}),
[types.replace]: (state, action) => state.map(i => {
return i[key] === action.item[key]
? action.item
: i;
})
}
}
// @todo, https://github.com/anywhichway/nano-memoize
export function createSelectors(statePath) {
let mem;
let preRes;
return {
find: (conditions) => (state) => {
if(mem === state) return preRes;
const subState = statePath.reduce((acc, curr) => acc[curr], state)
const res = subState.find(i => {
return Object.keys(conditions).reduce((match, key) => {
return i[key] === conditions[key];
}, true);
});
mem = state;
preRes = res;
return res || [];
}
}
}
export function createReducer(reducerAlias, {types, actions, key = 'id', initialState} = {}) {
if(!types) types = createActionTypes(reducerAlias);
if(!actions) actions = createActions(types, key);
if(!initialState) initialState = [];
return (state = initialState, action) => {
return actions[action.type]
? actions[action.type](state, action)
: state;
};
}
// my-reducer.js
export const types = createActionTypes('content');
export const actions = createDispatchers(types);
export const selectors = createSelectors(['content'])
export const contents = createReducer('content', { initialState, types });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment