【问题标题】:How do you filter data by category using an action and reducer in redux?如何在 redux 中使用 action 和 reducer 按类别过滤数据?
【发布时间】:2020-02-08 03:28:26
【问题描述】:

我正在构建一个过滤器,用户可以在其中按他们想要的类别来过滤数据,例如餐厅、酒吧、咖啡馆等。用户通过选择类别是否为真来使用过滤器false(即是否显示该特定类别),然后将其发送到我的操作和减速器。你会如何设置 reducer 来过滤数据,所以只显示真实的类别?

这是我的 filter.js 文件(商店和食物是真还是假):

onButtonPress() {
    const { shop, food } 
    = this.state;

this.props.filterRecommendations({ shop, food });

这是我的 action.js 文件:

export const filterRecommendations = ({ shop, food}) => {
    return {
        type: FILTER_RECOMMENDATIONS_BY_TYPE,
        payload: { shop, food }
    };
};

这是我的 reducer.js 文件:

export const reducer = (state = INITIAL_STATE, action) => {
    switch (action.type) {
    case FILTER_RECOMMENDATIONS_BY_TYPE:
        return {
            ...state,
                myRecommendations: state.myRecommendations.filter(
            item => item.type === action.payload
            )
        };
};

数据如下所示:

myRecommendations: [
    {
      id: '1',
      name: 'Yes Food',
      type: 'food'
    },
            {
      id: '2',
      name: 'Yes Shop',
      type: 'shop'
    },
]

上面的结果只是所有的数据都清除了。

【问题讨论】:

  • 你不应该使用 reducer 来获取值。减速器对于更新状态很有用。而是使用选择器。
  • 你能展示/链接到一个好的例子吗?我从来没有使用过选择器...
  • github.com/reduxjs/reselect。希望对您有所帮助。
  • 另见 redux 的文档,它们非常适合解释 here987654322@ 的方式和原因
  • @smashed-potatoes 你为什么删除你的答案?

标签: javascript reactjs react-native object redux


【解决方案1】:

您可以通过过滤数据来访问对象键:

state.myRecommendations.filter(item => action.payload[item.type])

【讨论】:

    【解决方案2】:

    @Yuvi 建议使用选择器是个好主意。它允许您在不改变减速器状态的情况下过滤列表。这对您的情况很重要,因为每次更改过滤器时,您当前的方法都会从您的状态中删除更多数据,即:

    1. 现在选择food > myRecommendations 仅包含food
    2. 选择shop > myRecommendations 为空,因为上面删除了shop 项目

    Redux 有文档概述了如何做到这一点here。 如果没有选择器,您将需要一种方法来在过滤器调用之间重新填充 myRecommendations 状态。

    使用类似reselect(见here)的东西可以通过记忆选择器来提高性能,但基本概念是:

    1. 将未过滤的结果保留在您的状态中
    2. 将您的过滤器选择存储为自己的状态
    3. 根据过滤器状态过滤需要的数据

    即:

    filter.js - 设置选中的过滤器

    onButtonPress() {
      const { shop, food } = this.state;
      this.props.setRecommendationsFilter({ shop, food });
    }
    

    无论您在何处定义操作名称

    const SET_RECOMMENDATIONS_FILTER = 'SET_RECOMMENDATIONS_FILTER';
    

    action.js

    export const setRecommendationsFilter = (filter) => {
      return {
        type: SET_RECOMMENDATIONS_FILTER,
        filter,
    };
    

    reducer.js - 存储选定的过滤器而不修改推荐数据

    export const reducer = (state = INITIAL_STATE, action) => {
      switch (action.type) {
        case SET_RECOMMENDATIONS_FILTER: {
          return {
            ...state,
            recommendationsFilter: action.filter,
          };
        }
      }
    };
    

    您在哪里使用过滤后的推荐 - 这是选择器的概念

    // 1. Bring in myRecommendations and recommendationsFilter from redux
    
    // 2. Filter
    /**
     * Get a filtered list of items, where the filter that matches
     * the recommendation 'type' is set to 'true'
     */
    const filteredRecommendations = myRecommendations.filter(
      (item) => recommendationsFilter[item.type]
    );
    
    // 3. Now use filteredRecommendations as you would have used myRecommendations
    

    当使用 reselect 之类的东西时,您可以将创建 filteredRecommendations 的逻辑与从 redux 中获取所需数据的逻辑放在一个选择器中,然后在您的 mapStateToProps 中使用该选择器(如 here 所述)。

    【讨论】:

      【解决方案3】:

      这可能对你有用

      点击按钮可以为所有过滤器传递数组

      onButtonPress() {
          const { shop, food } 
          = this.state;
      
      this.props.filterRecommendations([shop, food ]);
      
      export const filterRecommendations = (recommendationList ) => {
          return {
              type: FILTER_RECOMMENDATIONS_BY_TYPE,
              payload: recommendationList
          };
      };
      
      export const reducer = (state = INITIAL_STATE, action) => {
          switch (action.type) {
          case FILTER_RECOMMENDATIONS_BY_TYPE:
              return {
                  ...state,
                      myRecommendations: state.myRecommendations.filter(
                  item => action.payload.includes(item.type)
                  )
              };
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-20
        • 1970-01-01
        • 2021-10-28
        • 2017-03-17
        • 1970-01-01
        相关资源
        最近更新 更多