Redux: what is the correct way to filter a data array in reducer?
Remember always that the state is your "source of truth". Be wary of eliminating state on the basis of a temporary filter. Once you do so those items are gone. (The only way to get them back is to reset your state to the initialState, which may not be ideal.)
A better approach is to keep your items list as is, and simply store the search text.
const initialState = {
searchText: '',
items: [ 'hello', 'wahhh', 'yo' ]
};
export default function searchSimple(state = initialState, action) {
switch (action.type) {
case SEARCH_TEXT:
return Object.assign({}, state, {
searchText: action.text
});
}
}
Whilst your state won't contain the filtered list, it tells you everything you need to know to construct the filtered list.
Assuming you're using React, your "smart component" can be setup with the following mapStateToProps()
function:
function mapStateToProps(state) {
const { items, searchText } = state.searchSimple;
return {
filteredItems: items.filter((item) => item.startsWith(searchText))
};
}
Should you need this filtered list in more than one place, consider creating a "selector" function, as demonstrated in the Redux shopping cart example. https://github.com/reactjs/redux/blob/master/examples/shopping-cart/src/reducers/cart.js
It would look something like this:
export function filteredItems(state) {
const { items, searchText } = state.searchSimple;
return items.filter((item) => item.startsWith(searchText));
}
For a more advanced approach to selectors, check out the reselect library.
https://github.com/rackt/reselect
IMO, the right place to filter data is not directly in the reducers but in the selectors.
From redux docs:
Computing Derived Data
Reselect is a simple library for creating memoized, composable selector functions. Reselect selectors can be used to efficiently compute derived data from the Redux store.
I'm currently using selectors to filter and sort data.
- No data repetition in the state. You don't have to store a copy of the filtered items.
- The same data can be used in different components, each one using a different filter for example.
- You can combine selector applying many data computations using selector that you already have in the application.
- If you do right, your selectors will be pure functions, then you can easily test them.
- Use the same selector in many components.