NgRx 效果加载两​​次

Posted

技术标签:

【中文标题】NgRx 效果加载两​​次【英文标题】:NgRx Effects loaded twice 【发布时间】:2019-02-12 14:28:26 【问题描述】:

我有一个简单的功能模块,它提供服务并将自己的统计片段作为功能导入:

@NgModule(
  imports: [
    CommonModule,
    StoreModule.forFeature('alarms', alarmsReducer,  initialState: alarmsInitialState ),
    EffectsModule.forFeature([AlarmsEffects])
  ],
  declarations: [],
  providers: [
    AlarmsFacade,
    AlarmsService
  ]
)
export class AlarmsModule 

我在另外两个模块中导入这个模块,一个需要访问服务的页面和AppModule,因为我需要在这里导入它才能正确初始化状态。

当我检查 Redux DevTools 时,我可以清楚地看到 @ngrx/store/update-reducers 为功能 alarms 调用了两次。这会导致状态被冻结,停止所有效果(包括与警报功能无关的效果)。

下面的时间线可以显示问题(第三个@ngrx/store/update-reducers 动作在效果初始化后触发,而目前只有两个功能,它包含功能“警报”的减速器):

如何避免两次加载效果?我试图从AppModule 中删除该模块,但它打破了警报状态,因为我的选择器没有提供默认值。

【问题讨论】:

需要repro才能解决这个问题。 【参考方案1】:

这是我的问题:

升级到 ngrx 8 后,我没有从转换到 createEffect 的效果中删除 @Effect() 装饰器。

我从效果中删除了 dispatch: false(现在使用 createEffect),而不是将它们作为第二个参数放在箭头函数之后。

另见:Effect gets called twice when using StoreDevtoolsModule.instrument()

【讨论】:

谢谢,节省了我几个小时的调试时间! 也算我一个,希望我的朋友有不止一个赞 使用 createEffect 时删除 @Effect 解决了我的效果运行两次。【参考方案2】:

如果您需要多个模块中的状态切片,那么它显然不是功能状态,而是主要状态。因此,将该切片移动到您的主模块中并在那里为它实现减速器/效果。

【讨论】:

但是,问题是我必须在应用程序模块中放置很多切片,这就是为什么我最初想将内容拆分为模块,以便于阅读并避免我的应用模块中有大量 imports 数组。【参考方案3】:

如果您订阅可观察的效果本身,您还将获得两次触发效果,例如通过其他效果(而不是它们调度的动作)组合效果。

您可以通过订阅效果调度的操作来解决它,也可以使用shareReplay() 或其他类似的“热”可观察解决方案。

【讨论】:

【参考方案4】:

如果您使用 Angular 6,您可以使用 provideInRoot 功能。

@Injectable(
    providedIn: 'root'
)
export class MyEffects 

【讨论】:

不幸的是,这并不能解决这个问题:/

以上是关于NgRx 效果加载两​​次的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 ngrx-router-store 在 ngrx 效果中获取路由参数?

如何调用两次在ngrx效果中调用的服务?

Angular 7、Ngrx、Rxjs 6 - 访问延迟加载模块之间的状态

Angular ngrx - 显示加载中的 gif

@ngrx Effect 没有第二次运行

Ngrx - 减速器无法接收动作