NGRX 效果错误地触发了多个动作

NGRX effect incorrectly triggering multiple actions

我在单个 class 中定义了以下 NGRX 效果。 loadPage$ 效果很好。 loadSection$ 效果有效,但由于某种原因触发了 SetPages 操作和 SetSections 操作,即使我只返回 SetSections 操作。有什么想法吗?

效果

  @Effect()
  loadPages$: Observable<Action> = this.actions$.pipe(
    ofType<GetPages>(GET_PAGES),
    switchMap(() => {
      return this.loanService
        .getPages()
        .pipe(
          pluck('data', 'pages'),
          tap((pages: Page[]) => pages[0].active = true),
          map(pages => new SetPages(pages))
        );
    })
  );

  @Effect()
  loadSections$: Observable<Action> = this.actions$.pipe(
    ofType<SelectPage>(SELECT_PAGE),
    switchMap((action: SelectPage) => {
      console.log('loadPageSection$::action:', action);
      return this.loanService
        .getPageSections(action.payload)
        .pipe(
          pluck('data', 'pageSections'),
          map(sections => new SetSections(sections))
        );
    })
  );

操作: 在单个文件中定义的所有操作。

export const GET_PAGES = 'GET_PAGES';
export const SELECT_PAGE = 'SELECT_PAGE';
export const SET_PAGES = 'SET_PAGES';
export const SET_SECTIONS = 'SET_SECTIONS';

export class GetPages implements Action {
  readonly type = GET_PAGES;
}

export class SelectPage implements Action {
  readonly type = SELECT_PAGE;

  constructor(public payload: string) {
  }
}

export class SetPages implements Action {
  readonly type = SET_PAGES;

  constructor(public payload: Page[]) {
  }
}

export class SetSections implements Action {
  readonly type = SET_SECTIONS;

  constructor(public payload: Section[]) {
  }
}

export type LoanActions = GetPages | SelectPage | SetPages | SetSections;

减速器: 当我在 SET_PAGES 和 SET_SECTIONS 下放置 console.log 时,我看到在 loadSection$ 效果期间记录了两个实例。

export function loanReducer(state: LoanState = initialState, action: LoanActions) {
  switch (action.type) {
    case SELECT_PAGE:
      const pages = [ ...state.pages ];
      deactivatePage(pages);
      activatePage(action.payload, pages);
      return { ...state, pages };

    case SET_PAGES:
      return { ...state, pages: [ ...action.payload ] };

    case SET_SECTIONS:
      return { ...state, sections: [ ...action.payload ] };

    case GET_PAGES:
    default:
      return state;
  }
}

编辑添加 active/deactivate 函数

export const deactivatePage = (pages: Page[]) => chain(pages).find(page => page.active).set('active', false).value();

export const activatePage = (id: string, pages: Page[]) => chain(pages).find(obj => obj.id === id).set('active', true).value();

该操作由自定义组件内的按钮点击触发: this.store.dispatch(new SelectPage(page.id))

我找到了罪魁祸首。我在 Angular 应用程序中使用 GraphQL 后端和 Apollo 客户端来查询服务器。我正在使用 Apollo 客户端的 watchQuery 方法来获取数据。

根据 watchQuery 文档

As you know, Apollo.query method returns an Observable that emits a result, just once. Apollo.watchQuery also does the same, except it can emit multiple results. (The GraphQL query itself is still only sent once, but the watchQuery observable can also update if, for example, another query causes the object to be updated within Apollo Client's global cache.)

当切换数据上的活动标志时,它必须触发 watchQuery 的缓存被更新,从而触发另一个 Ngrx 效果。将我的 watchQuery 转换为普通的 query 解决了这个问题。