我的记忆选择器有问题。
在阅读https://redux.js.org/usage/deriving-data-selectors上的文档时,我截取了以下片段:
const state = {
a: {
first: 5
},
b: 10
}
const selectA = state => state.a
const selectB = state => state.b
const selectA1 = createSelector([selectA], a => a.first)
const selectResult = createSelector([selectA1, selectB], (a1, b) => {
console.log('Output selector running')
return a1 + b
})
const result = selectResult(state)
// Log: "Output selector running"
console.log(result)
// 15
const secondResult = selectResult(state)
// No log output
console.log(secondResult)
// 15
我的问题在于secondResult函数,记录结果。
这一切都是有一点前提的。
我的问题是:
- 我正在使用react with @reduxjs/工具包
- 我有一个待办事项清单
- 我创建了一个“todoAdapter”来将列表作为实体进行管理
- 我想使用memoized selected来更新一个“待办事项”,而不重新呈现整个列表来优化我的应用程序。
但是......
当我用“adapter.updateOne”分派更新时,标准选择器“SelectAll”每次(我认为)都更改ref。
范例
我从“slice”中找到了这个选择器
export const {
selectAll,
selectIds: selectTodosIDs,
selectTotal: selectTodosCount,
selectById: selectTodoById
} = todosSelector;
如果我创建这个选择器
export const selectIdsCustom = createSelector(
selectTodosIDs,
(ids) => {
console.log('execute output function');
return ....
}
)
一切正常(状态.待办事项. id没有明显变化)。
如果创建此选择器:
export const selectTodosCustom = createSelector(
selectAll,
(todos) => {
console.log('execute output function');
return ....
}
)
选择待办事项自定义运行“始终”。
为什么?
使用updateOne,我“仅“修改了“state.todos.entities”中的一个实体
我哪里错了??我不明白什么?
我的应用程序只是一个案例研究。完整的应用程序在:https://codesandbox.io/s/practical-hermann-60i7i
我只在typescript中创建了相同的应用程序,当我作为我的应用程序遇到这个问题时:
- 我下载了上面的原始应用程序表单链接(官方redux示例)
- npm安装
- npm启动
不过我这有些问题也在官方的例子里!
问题出在我的env?某个库版本?
1条答案
按热度按时间5gfr0r5j1#
当我用“adapter.updateOne”分派更新时,标准选择器“SelectAll”每次(我认为)都更改ref。
是的,你是对的。它是正确的。来自
@reduxjs/toolkit
的selectAll
依赖于来自实体状态的ids
和entities
。每次使用
adapter.updateOne
调度更新时,对entities
对象的引用都会发生变化。这是正常的,这就是immerjs(在reduxtoolkit的引擎盖下使用)如何提供正确的不变性:如果
entities
对象仍然是旧的,则选择器selectAll
将返回一个记忆值,其中第一个元素的标题不正确。要优化列表的重新呈现(实际上只对大型列表有用),您应该在父组件中使用选择器
selectIds
,在子组件中使用选择器selectById
。更新
在本例中,item没有改变ref,而在“实体”里面我改变了一个单独的道具。
这不对吗???
不,在使用redux时不能这样做。Redux是基于不变性的思想。任何状态的改变都会创建一个新的状态对象。更新实体只是状态对象的一个深层改变。并且在更新元素的路径上的所有对象都必须是新的。如果你不遵守这个规则,那么基本工具将不能正常工作。所有这些工具默认使用严格比较。
但是,即使选择器返回具有不同引用的相等数组,您仍然可以避免重新呈现组件。只需传递您自己的比较函数: