[ngrx效果在组件的构造函数中调度动作时未调用

问题描述 投票:1回答:1

这是我的应用程序模块:

@NgModule({
  declarations: [
    SampleA
  ],
  imports: [
    BrowserModule,
    EffectsModule.forRoot([APIEffects]),
    HttpClientModule,
    StoreModule.forRoot(reducers),
    StoreDevtoolsModule.instrument({
      maxAge: 25, // Retains last 25 states
      logOnly: environment.production, // Restrict extension to log-only mode
    }),
    KeyboardShortcutsModule.forRoot()
  ],
  providers: [
    APIService,
    {
      provide: HTTP_INTERCEPTORS,
      useClass: HttpMockRequestInterceptor,
      multi: true
    }
  ],
  bootstrap: [],
  entryComponents: [
    SampleComponent
  ]
})
export class AppModule{...}

这里是APIEffect

@Injectable()
export class APIEffects {
  fetchData$ = createEffect(() => this.actions$.pipe(
    ofType(Actions.apiFetchData),
    mergeMap((action) => this.apiService.fetchData(...action)
          .pipe(
            map(data => Actions.apiSuccess({ data })),
            catchError(() => of(Actions.apiCallFailed()))
          )
    )
  ));
}

现在,如果我在apiFetchData构造函数中分配SampleComponent操作,则不会调用该效果:

export class SampleComponent {
    constructor(private store: Store<{ state: State }>) {
        store.dispatch(Actions.apiFetchData(...))
    }
}

如果我稍后在组件的生命周期中调度相同的操作,则一切正常,并且效果发生了。

Redux DevTools中,我可以看到在effects init之前发生了动作分配。这是顺序:

@ngrx/store/init
[API] fetch data // this is the fetch data action
@ngrx/effects/init

所以我的问题是如何在构造组件之前强制效果初始​​化。

angular ngrx ngrx-effects
1个回答
0
投票

为了实现,您可能希望查看NGRX生命周期事件,例如ROOT_EFFECTS_INIT,如下所述:https://ngrx.io/guide/effects/lifecycle

使用APP_INITIALIZER注入令牌(很好的教程here)加上必要的语法糖,您可以构造一个应用程序初始化程序服务,该服务将延迟应用程序自举,直到注册了NGRX根效果为止(在这种情况下,不会初始化任何组件,并且您上面的逻辑在构造函数中应该起作用)。在最近的项目中,我走了一条类似的路:

export class AppInitializer {
  constructor(private readonly actions$: Actions) {}

  initialize() {
    return this.actions$.pipe(ofType(ROOT_EFFECTS_INIT));
  }
}
  return (): Promise<any> => {
    return appInitializer.initialize().toPromise();
  };
}

...最后将提供程序添加到您的模块中:

import { appInitializerFactory } from './app-initializer.factory';

export const APP_INITIALIZER_PROVIDER: Provider = {
  provide: APP_INITIALIZER,
  useFactory: appInitializerFactory,
  deps: [AppInitializer],
  multi: true,
};
// your module...
{
...
  providers: [APP_INITIALIZER_PROVIDER]
...
}
© www.soinside.com 2019 - 2024. All rights reserved.