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

Leave a Comment