当我想要排序或过滤数据时,如何查看 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"时,我想对最新过滤的数组进行排序。
我的问题:
- 如何在不重新计算的情况下实现此功能?
- 我可以不用重新选择实现吗?
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
}
},
)
我有一些数据作为对象数组。我会用 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
})
},
)
我的mapStateToProps:
let mapStateToProps = (state) =>{
let modernState = filterData(state)
return {
activePerson:modernState[state.active],
persons:modernState,
loading:state.loading,
active:state.active
}
}
- 如何在不重新计算的情况下实现此功能?
- 我可以不用重新选择实现吗?
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
}
},
)