Redux:在reducer中过滤数据数组的正确方法是什么?

时间:2015-11-30 16:42:07

标签: javascript redux

我想在搜索上过滤数组SEARCH_TEXT是一个on change行动 我与之混淆的是当按下删除键并且文本现在变为空时我如何返回状态,我想我可以在else语句中使用初始状态但我倾向于这是错误的?当我返回状态时,它已经准备好在if语句中被操作了。

简单的例子。

提前感谢。

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
      }

2 个答案:

答案 0 :(得分:79)

永远记住,国家是你的“真理之源”。警惕在临时过滤器的基础上消除状态。一旦你这样做,这些项目就不见了。 (让他们回来的唯一方法是将你的状态重置为initialState,这可能并不理想。)

更好的方法是保持您的商品清单不变,只需存储搜索文字。

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
            });
    }
}

虽然您的州不会包含已过滤的列表,但它会告诉您构建过滤列表时需要了解的所有内容。

假设您正在使用React,可以使用以下mapStateToProps()功能设置“智能组件”:

function mapStateToProps(state) {
    const { items, searchText } = state.searchSimple;
    return {
        filteredItems: items.filter((item) => item.startsWith(searchText))
    };
}

如果您需要在多个位置使用此筛选列表,请考虑创建“选择器”功能,如Redux购物车示例中所示。 https://github.com/reactjs/redux/blob/master/examples/shopping-cart/src/reducers/cart.js

它看起来像这样:

export function filteredItems(state) {
    const { items, searchText } = state.searchSimple;
    return items.filter((item) => item.startsWith(searchText));
}

有关选择器的更高级方法,请查看重新选择库。

https://github.com/rackt/reselect

答案 1 :(得分:16)

IMO,过滤数据的正确位置不是直接在reducer中,而是在选择器中。

来自redux docs:

Computing Derived Data

  

Reselect是一个用于创建memoized,可组合选择器函数的简单库。重选选择器可用于有效地计算Redux存储中的派生数据。

我目前正在使用选择器过滤排序数据。

  1. 状态中没有数据重复。您不必存储已过滤项目的副本。
  2. 相同的数据可用于不同的组件,例如每个组件使用不同的过滤器。
  3. 您可以使用应用程序中已有的选择器组合选择器应用许多数据计算。
  4. 如果你做得对,你的选择器将是纯函数,那么你可以轻松地测试它们。
  5. 在许多组件中使用相同的选择器。