什么时候在 ngrx/component-store 中使用 updater() 和 patchstate() ?

Lum*_*ous 2 ngrx ngrx-component-store

我正在使用 ngrx/component-store 并且到目前为止很喜欢它。拥有构建我自己的简单数组的先验商店知识,到目前为止,我唯一真正头痛的是当我必须更新数组并发现我必须始终为内部compare()管道创建一个新数组才能实现数组已更新。

无论如何,通读文档,它讨论了更新程序方法和 patchState。对我来说,他们做的事情完全相同,但他们的创作略有不同。您可以在方法内部调用 patchState,而 this.updater() 返回一个方法,为您提供可以在服务中公开的函数。每当我更新状态时,总是在网络调用之后。我假设在很多情况下您希望在没有网络调用的情况下更新状态,因此这就是为什么您希望有一个更新程序可供组件调用。问题是,如果更新程序和 patchState 确实在做同样的事情,那么在效果中调用更新程序或使用 patchState 是更好的做法,还是我在效果中放置了太多逻辑?

顺便说一句,文档说更新方法应该是一个纯函数。如果您使用它来将对象推送到数组上,那么它真的是纯粹的吗?

// adding the selectors so people know what components are subscribing to
readonly approvals$ = this.select(state => state.requestApprovals);
readonly registration$ = this.select(state => state);

readonly updateAssessment = this.effect(($judgement: Observable<{id: string, isApproved: boolean}>) => {
    return $judgement.pipe(
      switchMap((evaluation) => {
        const state = this.get();
        return this.requestApproval.patch(state.id, state.companyName, evaluation.id, evaluation.isApproved).pipe(
          tapResponse(
            (result) => {

             // is it better to call patchState()?
              this.patchState((state) => {
                for(let i = 0; i < state.requestApprovals.length; i++) {
                  if(state.requestApprovals[i].id == result.id) {
                    state.requestApprovals[i].isApproved = result.isApproved;
                  }
                }
                // the take away is you must assign a whole new array object when you update it.
                state.requestApprovals = Object.assign([], state.requestApprovals);
                return state;
              });

              // or this updater?
              // this.applyDecisionPatch(evaluation);
            },
                    // oh look! another updater reassigning my array to the state so
                    // it propagates to subscribers to reset the UI
            () => { this.reverseDecision(); }
          )
        );
      })
    );
  });

// this is private to make sure this can only be called after a network request
  private readonly applyDecisionPatch = this.updater((state, value: {id: string, isApproved: boolean}) => {
    for(let i = 0; i < state.requestApprovals.length; i++) {
      if(state.requestApprovals[i].id == value.id) {
        state.requestApprovals[i].isApproved = value.isApproved;
      }
    }
    state.requestApprovals = Object.assign([], state.requestApprovals);
    return state;
  });
Run Code Online (Sandbox Code Playgroud)

注意:ngrx-component-store 没有标签,因此无法对其进行标记。

tim*_*ver 8

Anupdater可以比作一个减速器。

所有修改状态的选项都应该以不可变的方式改变它。像 ngrx-immer 这样的库可以让这变得更容易。

主要区别在于updater接收当前状态,并且您可以根据它更改状态。例如有条件更新,或者可以与@ngrx/entity一起使用

使用setState和时patchState,您只需设置状态属性。 setState更新整个状态对象,而patchState只设置给定的属性,不影响状态对象的其余部分。当您只想设置状态时,这两种方法也更容易使用,因为您不必创建更新程序函数。

回答侧面的问题,push并不是一成不变的。它不是创建新实例,而是更新数组实例。

  • 恕我直言,应该始终通知订阅者。使用的技术应该不重要。换句话说,patchState 也应该通知订阅者。如果您需要当前状态,请使用 updater,否则 patchState 更容易使用恕我直言。 (4认同)