2

我有一些数据作为对象数组。我会用 redux 和 react-redux 对其进行排序或过滤。

我的初始状态

let initialState = {
  persons:[],
  active:0,
  loading:false,
  filter:"",
  field:"name",
  increase:true
}

由于过滤和排序是针对 UI 的,所以我尝试在容器(智能组件)中实现它。过去几天我在阅读 redux,react-redux 的文档,发现我需要使用reselect。因此,我创建了两个选择器:存储最新排序数据数组的sortData和存储最新过滤数据数组的filterData

选择器的参数 - 选择器监视的字段

let getPersons = (state) => state.persons
let getFilter = (state) => state.filter
let getField = (state) => state.field
let getIncrease = (state) => state.increase

排序数据

let sortData = createSelector(
  [getPersons, getField,getIncrease],
  (persons,field,increase) =>  {
    console.log("SORT");
    let sortarr = persons.slice(0);
    return sortarr.sort((a , b) => {
      if (a[field] > b[field])  return increase ?  1: -1
      if (a[field] < b[field])  return increase ? -1:1
      return 0
    })
  })

过滤数据

let filterData = createSelector(
  [sortData,getFilter],
  (persons,filter) => {
    return persons.filter( p =>{
      console.log("FILTER");
      return p.name.toLowerCase().indexOf(filter.toLowerCase()) !== -1
    })
  },
)
正如您在上面看到的,我的选择器filterData依赖于sortData而不是相反。当我 filterData 它只调用过滤器计算但是当我尝试对数据进行排序时它同时调用排序和过滤器。

我的mapStateToProps

let mapStateToProps = (state) =>{
  let modernState = filterData(state)
  return {
      activePerson:modernState[state.active],
      persons:modernState,
      loading:state.loading,
      active:state.active
    }
}
当我单击“过滤数据”时,我想过滤最新的排序数组,当我单击“排序数据”时,我想对最新过滤的数组进行排序。 我的问题:

  1. 如何在不重新计算的情况下实现此功能?
  2. 我可以在不重新选择的情况下实现它吗?

PS 我阅读了 Dan Abramov 的示例,但不幸的是,我无法将其应用于解决我的任务。更多代码:在此处输入链接描述

4

2 回答 2

2

您可以尝试以下操作,最好将其保存在一个文件中,然后在连接组件时将其用作选择器

// yourComponentSelector.js

let getPersons = (state) => state.persons
let getFilter = (state) => state.filter
let getField = (state) => state.field
let getIncrease = (state) => state.increase
let getLoading = (state) => state.loading
let getActive = (state) => state.active

let sortData = createSelector(
  [getPersons, getField,getIncrease],
  (persons,field,increase) =>  {
    console.log("SORT");
    let sortarr = persons.slice(0);
    return sortarr.sort((a , b) => {
      if (a[field] > b[field])  return increase ?  1: -1
      if (a[field] < b[field])  return increase ? -1:1
      return 0
    })
  })

function filterData(data, filter) {
   return data.filter(p => {
       console.log("FILTER");
       return p.name.toLowerCase().indexOf(filter.toLowerCase()) !== -1
   });
}

let filterDataSelector = createSelector(
   [sortData, filter],
   (persons, filter) => {
      return filterData(persons, filter)
   })

export const yourComponentSelector = createSelector(
  [filterDataSelector,
   getLoading,
   getActive
  ],
  (persons, loading, active) => {
    return {
       persons: persons,
       activePerson: persons[active],
       loading: loading,
       active: active
    }
  },
)

然后在你的组件中

   import { yourComponentSelector } from './yourComponentSelector.js';

   // instead of using your mapStatToProps function you can now use the selector

   export default connect(yourComponentSelector)(yourComponent);

所以简而言之

如果您需要对数据进行排序,它将重新计算过滤数据,因为 sortData 已更改,并且您想要过滤最近排序的数据,如果您的过滤器更改,它将重新计算 filterData 但不计算 sortData。重新选择的工作方式是,如果您传递给 createSelector 的参数之一发生了变化,它只会重新计算状态,因此在构建选择器时请注意这一点。

于 2016-04-18T08:26:42.297 回答
0

我认为您的选择器输入错误,因此filterData应该是以下内容的输入sortData并且getPersons应该是以下内容的输入filterData

let sortData = createSelector(
  [filterDataSelector, getField, getIncrease],
  (persons,field,increase) =>  {
    console.log("SORT");
    let sortarr = persons.slice(0);
    return sortarr.sort((a , b) => {
      if (a[field] > b[field])  return increase ?  1: -1
      if (a[field] < b[field])  return increase ? -1:1
      return 0
    })
  })

function filterData(data, filter) {
   return data.filter(p => {
       console.log("FILTER");
       return p.name.toLowerCase().indexOf(filter.toLowerCase()) !== -1
   });
}

let filterDataSelector = createSelector(
   [getPersons, filter],
   (persons, filter) => {
      return filterData(persons, filter)
})

export const yourComponentSelector = createSelector(
  [sortData,
   getLoading,
   getActive
  ],
  (persons, loading, active) => {
    return {
       persons: persons,
       activePerson: persons[active],
       loading: loading,
       active: active
    }
  },
)
于 2016-04-25T23:27:43.290 回答