es-reduce-list
v0.0.1
Published
Enables a reducer to reduce multiple items, useful for lists of objects.
Downloads
1
Readme
Reduce List
This module makes it easy to convert a reducer that reduces a single object, and use it to reduce a list of objects. You can specify which actions are applied to all objects, and which ones are applied only to specific objects.
Install
To install:
$ npm install es-reduce-list
Usage
Let's say we are building out a TodoMVC, and we have built the following reducer to reduce a single Todo item:
import {
TOGGLE_COMPLETE,
EDIT_TEXT,
} from 'actions';
const reduceTodo = (state, action) => {
switch (action.type) {
case TOGGLE_COMPLETE:
return {
...state,
complete: !state.complete,
};
case EDIT_TEXT:
return {
...state,
text: action.payload,
};
}
};
We can toggle whether the todo item is complete or not, as well as edit the todo.
But now we want to be able to reduce a list of items, not just one. We can do this by using reduceList
:
import reduceList from 'es-reduce-list';
const reduceTodoList = (state = {}, action) => {
return reduceList(
state,
action,
reduceTodo,
[ TOGGLE_COMPLETE, EDIT_TEXT ],
(action) => action.id,
);
};
We first pass in state
, the action
, and reduceTodo
to the function. Next, we have to pass in an array of actions that are 'single-item' actions, meaning that they target a specific item (they should not be applied to the entire list). All other actions will be applied to each item in the list. Lastly, we provide a function that we can use to get the id
of the targeted item from the action
.
Our state must be an object, where each key is the id
of the item, and each item has a property id
which is the same as the key. For our todo list it would look like:
{
0: { id: 0, text: 'Todo 1', completed: false },
1: { id: 1, text: 'The last thing I want to do', completed: false },
...
}
Our action must also have the id
of the targeted item somewhere in it:
{
type: 'TOGGLE_COMPLETE',
id: 1,
}
If we wanted to have a COMPLETE_ALL
action, we would first update the reduceTodo
reducer:
import {
TOGGLE_COMPLETE,
EDIT_TEXT,
COMPLETE_ALL,
} from 'actions';
const reduceTodo = (state, action) => {
switch (action.type) {
case TOGGLE_COMPLETE:
return {
...state,
complete: !state.complete,
};
case EDIT_TEXT:
return {
...state,
text: action.payload,
};
case COMPLETE_ALL:
return {
...state,
complete: true,
};
}
};
...and that's it! Because it's not specified in our list of 'single-item' actions, it will be applied to every single item in the list.
But how would we add new todos?
We can modify reduceTodoList
like so:
import reduceList from 'es-reduce-list';
const reduceTodoList = (state = {}, action) => {
if (action.type === ADD_NEW_TODO) {
return {
...state,
[action.payload.id]: action.payload,
};
} else {
return reduceList(
state,
action,
reduceTodo,
[ TOGGLE_COMPLETE, EDIT_TEXT ],
(action) => action.id,
);
}
};