Angular 2 - ngrx订阅在每次状态更改时运行

时间:2017-04-26 12:38:35

标签: javascript angular redux ngrx

我有一个基本的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$处理程序也会运行。

所有的一点是只运行改变的部分,或者我错了?

3 个答案:

答案 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语句的默认部分,它可能会在不更改任何值的情况下深度复制状态-因此返回新的引用,选择器将再次执行。