【问题标题】:How to handle NGRX control flow如何处理 NGRX 控制流
【发布时间】:2021-05-25 21:40:09
【问题描述】:

我是 angular + ngrx 的新手,并且对适当的大规模控制流有疑问。假设我有一个Cars 组件,它可以加载汽车列表并可以创建一辆新车。一旦这些效果执行,它们将调度 SUCCESSFAILURE 动作。在我的ngOnInit 中,我订阅了每个成功/失败的操作以执行适当的操作 - 例如:

ngOnInit() {
    this.actions$
      .pipe(
        ofType<fromCarsActions.GetCarsSuccessAction>(fromCarsActions.CarsActionTypes.GET_CARS_SUCCESS),
        takeUntil(this.unsubscribe$)
      )
      .subscribe(results => {
        // do something if load all cars SUCCEEDS
      });


      this.actions$
      .pipe(
        ofType<fromCarsActions.GetCarsFailureAction>(fromCarsActions.CarsActionTypes.GET_CARS_FAILURE),
        takeUntil(this.unsubscribe$)
      )
      .subscribe(results => {
        // do something if load all cars FAILS
      });


      this.actions$
      .pipe(
        ofType<fromCarsActions.AddCarSuccessAction>(fromCarsActions.CarsActionTypes.ADD_CAR_SUCCESS),
        takeUntil(this.unsubscribe$)
      )
      .subscribe(results => {
        // do something if add car SUCCEEDS
      });


      this.actions$
      .pipe(
        ofType<fromCarsActions.AddCarsFailureAction>(fromCarsActions.CarsActionTypes.ADD_CAR_FAILURE),
        takeUntil(this.unsubscribe$)
      )
      .subscribe(results => {
        // do something if add car FAILS
      });
}

订阅所有这些 SUCCESS/FAILURE 操作(如果只有少数几个)很好,但对于更复杂的组件很容易很快失控。

我可以做的另一个选择是在效果本身中调度适当的操作,但这不会使效果非常可重用。

所以我的问题是,对于使用 NGRX 与后端通信以轻松管理订阅/收听多个不同效果成功/失败的组件的最佳做法是什么?

我知道这是一个有点抽象的问题,所以如果我能澄清任何事情,请告诉我。

【问题讨论】:

    标签: angular ngrx


    【解决方案1】:

    您不需要订阅任何操作。

    你应该对 reducer 和 effects 中的动作做出反应。而 effect 最终应该会派发另一个动作。但是您可以将其用于副作用,例如导航。

    因此,您在 ngOnInit 中考虑的大部分内容都应该在 reducer 中。

    【讨论】:

    • 对,但据我了解,reducer 应该只是改变状态。例如,如果我需要在成功添加汽车后导航到一个页面 - 应该在哪里处理?或者你是说成功添加汽车后,我的效果需要调度一个导航到另一个页面的动作?感谢您的回复!
    • 成功添加汽车后,您可以订阅选择器。在添加汽车时更新商店时为 newCarAdded 创建一个选择器,选择器将被订阅。您可以在应用中的任何位置访问此选择器,这是优势。
    • 我不同意。任何副作用都应进入效果部分。所以导航应该去那里。 See this answer
    【解决方案2】:

    你触发了动作

    Action 将触发 Reducer(仅更新存储)或 Effect(处理负责从 DB 获取数据的服务)

    然后您可以订阅 Selector 以获取更改。

    在你的情况下创建动作 -

    export const loadCars = createAction('Load Car data');
    
    export const getcarsSuccess = createAction('Get Car data Success', props<{ carData: any }>());
    
    export const getCarsError = createAction('Get Car data Error', props<{ errorResponse: any}>());
    
    export const createCars = createAction('Add Car data');
    
    export const createCarsSuccess = createAction('Add Car data Success', props<{ carData: any }>());
    
    export const createCarsError = createAction('Add Car data Error', props<{ errorResponse: any}>());
    

    上面的动作可以触发一个效果器或者reducer

    生效:

     @Effect()
      public loadCarData$ = createEffect(() => this.actions$.pipe(
        ofType(actions.loadCars ) ...
    

    在减速器中:

     const initReducer = createReducer(
      initialIState,
      on(actiona.loadCarData, state => (state)))
    

    在选择器中:

    export const carDataLoaded = (state: fromReducer.carData) => state.carData ;
    
    export const getCarData = createSelector(
      getInitState,
      carDataLoaded 
    );
    

    终于在组件中:

    可以订阅选择器getCarData,所以组件-动作-效果-reducer-选择器-组件

    在比赛中

     private carStore: Store<carStore> 
      this.carStore.dispatch(new loadCars ()); //dispatch load Cars Action
     this.carStore.pipe(select(
                getCarData })
            ).subscribe(cars => console.log(cars)) // subscribe to selector
    

    注意:您可以直接从您提到的组件订阅任何操作,但这不符合使用 NGRX 状态管理的目的。

    从 Angular 应用程序中的任何位置更新 NGRX 商店,并从应用程序中您想要的任何地方访问商店数据。无需担心维护数据状态。

    【讨论】:

    • 谢谢!所以基本上,诀窍是让 reducer 启动操作以更新状态 - 在组件中,订阅状态以执行进一步的操作
    • 不,这是不正确的。不要监听组件中的状态变化来触发进一步的操作。应始终在效果中触发进一步的操作。
    猜你喜欢
    • 2019-11-17
    • 2017-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多