【问题标题】:Related entities in separate reducers in ngrxngrx 中单独减速器中的相关实体
【发布时间】:2017-11-19 06:34:30
【问题描述】:

我正在开发我的第一个 angular ngrx 应用程序,但相关实体存在问题。我有两个 reducer,一个叫做 Page,一个叫做 Section。下面是该结构的简化版本。 section 对象有一个 pages 数组,其 pageIds 指向 page reducer 中的页面。

// section.reducer.ts
sections: {
    1: {
        id: 1,
        title: 'Section 1',
        pages: [1,2,3]
    }
}

// page.reducer.ts
pages: {
    1: {
        id: 1,
        title: 'Page 1'
    },
    2: {
        id: 2,
        title: 'Page 2'
    }
    3: {
        id: 3,
        title: 'Page 3'
    }
}

当我想添加一个新页面并将其添加到一个部分时,我正在苦苦挣扎。我的第一个想法是调度一个 AddPage 操作并在两个减速器中处理它。那么问题是 Page 对象是在页面缩减器中创建的,因此部分缩减器不知道它。我必须至少在 section reducer 中有 pageId。然后我认为我可以使用新创建的页面发送 AddPageSuccess 以便节缩减器可以处理它。这种方法的问题在于,reducer 中没有对 store 的引用,因此我无法调度任何操作。因此,我尝试像 @effect 一样添加它。这可能会奏效,但我不确定这是否是“正确”的方式。我的印象是效果应该用于异步数据,例如休息调用。在这种情况下,一切都是同步的,但动作相互依赖。 @effects 是实现这种行为相互依赖的场景的“有效”方式,还是这种设计错误。

另一种方法是将所有状态都放在同一个减速器中,但该减速器会很大,因为每个部分都会有很多逻辑。

【问题讨论】:

    标签: angular redux ngrx


    【解决方案1】:

    效果是针对副作用的,您对效果解决方案的想法在我看来是完全有效的。您正在添加 Page ,但 Section 也应该意识到这一点。这肯定是副作用吧?所以,effects 是一个很好的解决方案。

    【讨论】:

      【解决方案2】:

      @Effects 用于具有副作用的操作。到目前为止,您已经提到了纯操作(这些没有副作用),所以这些应该由减速器处理。

      你应该有两个动作,每个减速器一个:

      ADD_SECTION_PAGE
      ADD_PAGE
      

      当您想要添加页面并将其添加到部分时,请从商店发送两条消息:

      onAddPage() {
          this.store.dispatch(new AddSectionPageAction({sectionId:1, page:4 }));
          this.store.dispatch(new AddPageAction({ id:4, title: 'Some Page Title' }));
      }
      

      SectionReducer 将根据 sectionId 找到该部分,并将新页面添加到 pages 数组中。

      PageReducer 会将页面添加到 PageState。

      ID 的计算可以在你的 reducer 中进行:

      newId = Object.keys(pagesState).length > 0 
        ? Object.keys(pagesState).sort().reverse()[0] + 1 : 1;
      

      或者,如果您通过 Web API 调用添加页面,请通过 @effect 添加页面,并将 id 传递给 ADD_PAGE 操作。

      【讨论】:

      • 不确定我是否理解您的建议。我想要做的是添加一个新页面,同时将其添加到 Sections pages 数组之一,而不是添加一个新 Section。由于在分派 ADD_PAGE 操作时页面没有 ID,因此节缩减器无法将 i 添加到节页面数组之一。这意味着我必须首先添加页面,等待它完成以便它有一个 ID,然后将它添加到sections 数组中。当我现在写这篇文章时,这听起来像是一个副作用。
      • 我明白了,我现在明白了。我仍然认为它没有副作用。
      • 好的,现在看到您编辑的响应,使用这种方法,我需要知道调度操作的组件中已经存在的新页面的 ID。这感觉像是业务逻辑,不应该在 reducer 中吗?对于这个实现,我认为我使用这种方法是安全的,因为我使用的是 GUID,但如果我有一个数字作为 id,它需要是唯一的,并且查找唯一 id 的逻辑不应该在调度的组件中行动?
      • 你是对的。我会在操作中为 id 传递 0,并让你的 reducer 计算唯一 ID
      • 但是我们又回到了我原来的问题......节缩减器必须在新页面上具有和 ID 才能将其添加到 Sections pages 数组中。这意味着 ADD_PAGE 操作必须先完成,以便页面有一个 ID,然后将其添加到一个部分
      【解决方案3】:

      基于https://medium.com/@viestursv/how-to-get-store-state-in-ngrx-effect-fab9e9c8f087

      您可以访问 Effect 类中的状态。请参阅下面的相关代码。 Selector 是一种对状态进行切片的方法,您必须在 reducer 中将状态与相关数据一起分发以更新状态。

      ```

      @Effect() specialEffect$ = this.actions$
          .ofType(ADD_LINE)
          .withLatestFrom([
            this.store$.select(state => state.lines), 
            this.store$.select(state => state.pages])
          .map(([action: Action, linesOrPages: Lines|Pages]) => {
            // Do something ...
          });

      【讨论】:

        猜你喜欢
        • 2022-08-09
        • 1970-01-01
        • 2019-04-20
        • 1970-01-01
        • 1970-01-01
        • 2017-08-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多