【问题标题】:NGRX effect incorrectly triggering multiple actionsNGRX 效果错误地触发了多个动作
【发布时间】:2020-02-19 22:18:29
【问题描述】:

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

减速器: 当我将 console.log 放在 SET_PAGES 和 SET_SECTIONS 下时,我看到在 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))

【问题讨论】:

  • pages 数组包含像 { id:1, label:'Label', active:false } 这样的对象。 deactivatePage 查找 active 为 true 的对象并将其设置为 false。 activatePage 在数组中查找 id 匹配的对象并将 active 属性设置为 true。我想既然我在那些函数中使用它之前复制了 pages 数组,那就没问题了。
  • 如果这些是纯函数就好了。在每个ofType 之后,你可以放一个tap((act) =&gt; console.log(“effect”, act)) 并搜索动作的发送位置
  • 通过注释掉 deactivatePageactivatePage 方法进行测试。仍然奇怪的行为,但不同。单击按钮会触发loadSection$ 效果。注释掉函数后,SetPages 只在第一次点击时触发。然后每次后续点击只会触发 SetSections。
  • 你能贴出调度动作和deactivatePage、activatePage代码的代码吗?
  • 作为编辑添加到原始帖子

标签: angular typescript ngrx effects


【解决方案1】:

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

根据watchQuery 文档

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-02
    • 2019-01-31
    • 1970-01-01
    • 2017-12-30
    • 1970-01-01
    • 2019-07-02
    • 1970-01-01
    相关资源
    最近更新 更多