当我想要排序或过滤数据时,如何查看 redux 容器中的数据状态?

How can I watch for state of data in redux container, when I want to sort or filter it?

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

我的初始状态

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

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

arguments of selectors - 选择器监视字段:

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 但不是相反。 当我过滤数据时,它只调用过滤计算,但当我尝试对数据进行排序时,它同时调用排序和过滤。

我的mapStateToProps:

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

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

P.S。我阅读了 Dan Abramov 的示例,但不幸的是,我无法将其应用于解决我的任务。 更多代码:enter link description here

您可以尝试以下方法,最好将其保存在一个文件中,然后将其用作您的select或在连接组件时使用

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

简而言之

如果您需要对数据进行排序,它将重新计算 filteredData,因为 sortData 已更改并且您想过滤最近排序的数据,如果您的过滤器发生更改,它将重新计算 filterData 而不是 sortData。 re-select 的工作方式是,如果您传递给 createSelector 的参数之一发生变化,它只会重新计算状态,因此在构建 selectors.

时请注意这一点

我认为您对选择器的输入有误,因此 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
    }
  },
)