Redux: what is the correct way to filter a data array in reducer?

i want to filter an array on search SEARCH_TEXT is an on change action what I'm confused with is how i return the state when the delete key is pressed and the text now becomes empty, i figure i could use initial state in the else statement but my inclination is this is wrong? when i return just state it has all ready been manipulated in the if statement.

simple example.

thanks in advance.

const initialState =  ['hello', 'wahhh', 'yo'];

export default function searchSimple(state = initialState, action) {
  switch (action.type) {
    case SEARCH_TEXT:
      if(action.text.length > 0){
        return state.filter(item =>
          item.startsWith(action.text)
        )
      }
      else {
        return state
      }

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.

  1. No data repetition in the state. You don't have to store a copy of the filtered items.
  2. The same data can be used in different components, each one using a different filter for example.
  3. You can combine selector applying many data computations using selector that you already have in the application.
  4. If you do right, your selectors will be pure functions, then you can easily test them.
  5. Use the same selector in many components.