@lsmoura/create-reducer
v1.0.2
Published
`yarn add @lsmoura/create-reducer`
Downloads
2
Readme
Create Reducer
yarn add @lsmoura/create-reducer
This helper lets the user creates simple or nested reducers.
API
createReducer(initialState, handlers [, wrapper])
initialState is an object or value that represents the initial state.
handlers is an object that has the format ACTION_NAME: reducer
or key: handlers
.
Some examples:
const handlers = {
'ADD': (state, action) => (state + 1),
'SUBTRACT': (state, action) => (state - 1),
};
or
const handlers = {
'todo': {
'ADD_TODO': (state, action) => state.concat(action.value),
},
'counter': {
'ADD': (state, action) => (state + 1),
'SUBTRACT': (state, action) => (state - 1),
},
};
or even
const counterHandlers = {
'ADD': (state, action) => (state + 1),
'SUBTRACT': (state, action) => (state - 1),
};
const handlers = {
'todo': {
'ADD_TODO': (state, action) => state.concat(action.value),
},
'counter': counterHandlers,
'counter2': counterHandlers,
};
nested parameters will have their state extracted from the original state and the result will be assigned back to the key.
you can nest parameters as much as you like:
const counterHandlers = {
'ADD': (state, action) => (state + 1),
'SUBTRACT': (state, action) => (state - 1),
};
const handlers = {
'deeply': {
'nested': {
'counter': counterHandlers,
},
},
};
the createReducer function will ignore any handler key that starts with $
.
It will also send a default state for your reducer function if you provide
a key of $defaultState
and there is no state value assigned to the key you
provide:
const handlers = {
'$defaultState': 0,
'ADD': (state, action) => (state + 1),
'SUBTRACT': (state, action) => (state - 1),
};
wrapper is an optional parameter. it must be a function that will wrap your
reducer function. It's recommended to use objectActionHandler
as this
parameter to help reduce the amount of "spreading" or
"Assigning"
on your reducers.
objectActionHandler
This is a wrapper helper that assigns the returned state to the existing one, like so:
function(reducer, state, action) {
const reducerResult = reducer(state, action);
return Object.assign({}, state, reducerResult);
}
Examples
Every example assumes that the module is imported in the following way:
import import createReducer, { objectActionHandler } from '@lsmoura/create-reducer';
Very simple counter
const reducer = createReducer(
0,
{
'ADD': (state, action) => (state + 1),
'SUBTRACT': (state) => (state - 1),
},
objectActionHandler
);
Counter with default state
const reducer = createReducer(
undefined,
{
'$defaultState': 0,
'ADD': (state, action) => (state + 1),
'SUBTRACT': (state) => (state - 1),
},
objectActionHandler
);
Multiple counters that answer to the same action type
const counterHandlers = {
'$defaultState': 0,
'ADD': (state, action) => (state + 1),
'SUBTRACT': (state) => (state - 1),
};
const reducer = createReducer(
{},
{
counter: counterHandlers,
counter2: counterHandlers,
},
objectActionHandler
);
Mixed stuff
const handleAddSubtract = {
'$defaultState': 0,
'ADD': (state, action) => (state + 1),
'SUBTRACT': (state) => (state - 1),
};
const handleAddTodo = {
'$defaultState': [],
'TODO_INSERT': (state, action) => Array.concat(state, action.value),
};
const reducer = createReducer(
defaultState,
{
'ADD': (state, action) => ({ action_count: 1 + (state.action_count || 0) }),
counter: handleAddSubtract,
counter2: handleAddSubtract,
nesting_todos: {
inner_object: {
todos: handleAddTodo,
},
},
nested: nestedReducer.handlers,
},
objectActionHandler
);