编辑
对于这种情况,我正在睡觉和做梦(真的哈哈),用一个简单(但可能仍然没有必要)的解决方案。您必须在过滤器结果上返回一个原始类型,这样您就可以在第二个选择器上返回JSON.stringify()
它。JSON.parse()
以下测试套件通过:
const state = {
list: [
{ id: 1, active: true },
{ id: 2, active: false },
{ id: 3, active: false },
{ id: 4, active: false }
]
}
const getFilteredListIds = createSelector(
(state) => JSON.stringify(state.list.filter((object) => !!object.active)),
(filteredList) => JSON.parse(filteredList).map((object) => object.id)
)
expect(getFilteredListIds.recomputations()).toEqual(0)
expect(getFilteredListIds(state)).toEqual([1])
expect(getFilteredListIds.recomputations()).toEqual(1)
expect(getFilteredListIds(state)).toEqual([1])
expect(getFilteredListIds.recomputations()).toEqual(1)
const newState = {
list: [
...state.list,
{ id: 5, active: false } // should not change subset
]
}
expect(getFilteredListIds(newState)).toEqual([1]) // subset didn't change
expect(getFilteredListIds.recomputations()).toEqual(1) // pass :)
但是,根据您的用例,它可能比每次调用都进行过滤要慢。如果您测试该性能,请与我们分享。
第一篇文章
正如我在评论中所说,您实现的方式createSelector
毫无用处。
const state = {
list: [
{ id: 1, active: true },
{ id: 2, active: false },
{ id: 3, active: false },
{ id: 4, active: false }
]
}
const getFilteredListIds = createSelector(
(state) => state.list.filter((object) => !!object.active),
(filteredList) => filteredList.map((object) => object.id)
)
expect(getFilteredListIds.recomputations()).toEqual(0)
expect(getFilteredListIds(state)).toEqual([1])
expect(getFilteredListIds.recomputations()).toEqual(1)
expect(getFilteredListIds(state)).toEqual([1])
expect(getFilteredListIds.recomputations()).toEqual(1) // fail
首先,我做了一些调整来解决第一个问题。
const state = {
list: [
{ id: 1, active: true },
{ id: 2, active: false },
{ id: 3, active: false },
{ id: 4, active: false }
]
}
const getList = (state) => state.list
// it makes filter only happen if state.list changes
const getFilteredList = createSelector(
getList,
(list) => list.filter((object) => !!object.active)
)
const getFilteredListIds = createSelector(
getFilteredList,
(filteredList) => filteredList.map((object) => object.id)
)
expect(getFilteredListIds.recomputations()).toEqual(0)
expect(getFilteredListIds(state)).toEqual([1])
expect(getFilteredListIds.recomputations()).toEqual(1)
expect(getFilteredListIds(state)).toEqual([1])
expect(getFilteredListIds.recomputations()).toEqual(1)
// everything pass
现在你的问题是有效的:
如果对象或过滤列表发生更改,是否有可能只获得一个新对象?
你想要的是这个,对吧?
const newState = {
list: [
...state.list,
{ id: 5, active: false } // should not change subset
]
}
expect(getFilteredListIds(newState)).toEqual([1]) // subset didn't change
expect(getFilteredListIds.recomputations()).toEqual(1) // fail
但最后一行将失败,因为recomputations()
将是 2。
我认为解决这个问题的唯一方法是让filteredList
你的状态成为记忆的一部分,但这可能很奇怪。