首页 > 解决方案 > NGRX 效果错误地触发了多个动作

问题描述

我在单个类中定义了以下 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;

Reducers : 当我在 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;
  }
}

编辑添加激活/停用功能

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))

标签: angulartypescriptngrxeffects

解决方案


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

根据watchQuery文档

如您所知,Apollo.query 方法只返回一个发出结果的 Observable。Apollo.watchQuery 也做同样的事情,除了它可以发出多个结果。(GraphQL 查询本身仍然只发送一次,但是例如,如果另一个查询导致对象在 Apollo 客户端的全局缓存中更新,则 watchQuery observable 也可以更新。)

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


推荐阅读