我有一个基本的redux实现与ngrx / store。
// root reducer
export const root = {
posts: fromPosts.reducer,
purchases: fromPurchases.reducer
}
export function getAllPosts( state ) {
return fromPosts.getAll(state.posts);
}
export function getAllPurchases( state ) {
return fromPurchases.getAll(state.purchases);
}
在我的组件中,我选择了状态片段。
this.posts$ = store.select(getAllPosts).do(c => console.log('posts$ change'));
this.purchases$ = store.select(getAllPurchases).do(c => console.log('purchases$ change'));
但是在对状态的每次更改中,处理程序都在运行。例如,当我添加帖子时,purchases$
处理程序也会运行。
所有的一点是只运行改变的部分,或者我错了?
答案 0 :(得分:1)
这个答案是错误的,但由于某种原因,它被接受了。 select
的实施使用distinctUntilChanged
,因此问题可能存在于OP的getAll
函数的实现中。
每当将一个动作调度到商店时,它就会被传递给组合的减速器并组成一个新的状态。然后发出新的状态。
因此,即使选定的状态切片未发生变化,您的两个观察者都会看到向do
运算符发出的值。
但是,使用distinctUntilChanged
运算符更改此行为很简单:
import 'rxjs/add/operator/distinctUntilChanged';
this.posts$ = store.select(getAllPosts)
.distinctUntilChanged()
.do(c => console.log('posts$ change'));
distinctUntilChanged
将确保observable仅在值实际更改时发出,因此如果您选择的状态切片未更改,则不会发出任何内容。
答案 1 :(得分:0)
您的选择器未使用createSelector。
使用createSelector&当状态改变时,createSelector根据它的参数值记忆返回值。
当使用相同参数再次调用使用createSelector定义的函数时,会给出memoized返回值&其余的选择器代码没有运行。
/**
* Every reducer module exports selector functions, however child reducers
* have no knowledge of the overall state tree. To make them usable, we
* need to make new selectors that wrap them.
*
* The createSelector function creates very efficient selectors that are memoized and
* only recompute when arguments change. The created selectors can also be composed
* together to select different pieces of state.
*/
export const getBookEntitiesState = createSelector(
getBooksState,
state => state.books
);
使用示例(尽管这是一个旧线程,示例来自较新的NGRX) https://github.com/ngrx/platform/blob/master/example-app/app/books/reducers/index.ts#L58
答案 2 :(得分:-2)
由于select的实现使用distinctUntilChanged, 和
distinctUntilChanged默认使用===比较,对象引用 必须匹配。 https://www.learnrxjs.io/operators/filtering/distinctuntilchanged.html
问题可能出在以下事实上:无论将什么动作调度到化简器,您都将返回状态的新引用(即使状态值未更改)。
检查您的reducer switch语句的默认部分,它可能会在不更改任何值的情况下深度复制状态-因此返回新的引用,选择器将再次执行。