ngrx 8影响其他类型的调度动作

Posted

技术标签:

【中文标题】ngrx 8影响其他类型的调度动作【英文标题】:ngrx 8 effects dispatch action of other type 【发布时间】:2019-12-19 14:48:46 【问题描述】:

我在这里与您联系关于ngrx 效果,我正在尝试做的是有一个功能登录,它分配一个动作类型的登录,并且对这个动作的影响将使用我的服务来进行api 调用。 在这个返回令牌之后,我想分派另外两个动作,一个是 getUserMenu 类型,一个是 getUserInfo 类型。这两个动作的类型不同,效果也不同。

最后我有 3 家商店: 一个用于令牌和身份验证 一个用于用户信息 一个用于菜单信息

我试过这样的事情:

login = createEffect(
  () =>
  this.actions$
  .pipe(
  ofType(authLogin),
    tap(action => 
    console.log("EFFECT LOGINNNN");
    return this.authService.postLogin(action.username, 
      action.password).pipe(
        map((data: any) => 
          console.log("AUTHTHHTHTH DATATA ", data);
          let props = data.token;
          let payload = 
            token: data.token,
            isAuthenticated: true
          
      this.store.dispatch(moMenuHttpGetListAction(US_ID: action.username));  
      this.store.dispatch(userHttpGetInfoAction(US_ID:action.username));
      this.localStorageService.setItem(AUTH_KEY, payload);
    ))
  )
),
 dispatch: true 
);

如果我设置调度错误登录工作,但没有调用获取用户信息和用户菜单的方法 但是当我设置 dispatch true 我有同样效果的无限循环 动作 moMenuHttpGetListAction 看起来像这样:

moMenuHttpGetListEffect = createEffect(
     () => this.actions$.pipe(
        ofType(moMenuHttpGetListAction),
        switchMap(action => 
          console.log("MOMENU LOGINNNN");

          return this.moMenuService.getKmApplications(action.US_ID).pipe(
          map((data: any) => 
            console.log("MOMENU DATATA ", data);
            console.log("MOMENU DATATA ", action.US_ID);
            let payload = 
              MO_MENU: data
            

          this.store.dispatch(moMenuSetListAction(payload: data));
           this.localStorageService.setItem(MENU_KEY, payload);
          ))
        )
        ),
     dispatch: false 
  );

但是当我将 dispatch 设置为 true 时,我得到了编译错误。 我的动作看起来像:

import  createAction  from "@ngrx/store";
import  props  from "@ngrx/store";
import  MoMenu, MoMenuState  from "./mo_menu.models";

//TODO CHANGER ME_ID en US_ID
export const moMenuGetErrorAction = createAction("[User] Get Info");
export const moMenuGetIsLoadingAction = createAction("[User] Get Info");

export const moMenuSetErrorAction = createAction('[MoMenu] HTTP GET ACTION',
    props<error: string>()
    );
export const moMenuSetLoadingAction = createAction('[MoMenu] HTTP GET ACTION',
    props<loading: boolean>()
    );
export const moMenuHttpGetListAction = createAction('[MoMenu] HTTP GETLIST  ACTION',
    props<US_ID: string>()
    );
export const moMenuHttpGetListErrorAction = createAction('[MoMenu] HTTP GET ACTION Error',
    props<error: any>()
    );

export const moMenuGetListAction = createAction("[MoMenu] Get List");
export const moMenuSetListAction = createAction("[MoMenu] Set Mo Menu List",
    props<payload: MoMenu[]>());
export const moMenuDeleteAction = createAction("[MoMenu] Delete List");

这是有人要求我补充的两个减速器:

Ngrx 对我来说有点新,所以我很想在这方面提供一些帮助 =)

import  AuthState  from './auth.models';
import  authLogin, 
  authLogout ,
  authGetErrorAction,
  authGetIsLoadingAction,
  authSetErrorAction,
  authSetIsLoadingAction
 from './auth.actions';
import  createReducer, on, Action  from '@ngrx/store';

export const initialState: AuthState = 
  isAuthenticated: false,
  token: undefined,
  isLoading: false,
  HttpResponse: undefined
;

const reducer = createReducer(
  initialState,
    on(authSetErrorAction,  (state,  error ) => (
    ...state, HttpResponse:  error
  )),
   on(authSetIsLoadingAction,  (state,  isLoading ) => (
    ...state, isLoading: isLoading 
  )),

  on(authLogin, state => ( ...state, isAuthenticated: true )),
  on(authLogout, state => ( ...state, isAuthenticated: false ))
);

export function authReducer(
  state: AuthState | undefined,
  action: Action
): AuthState 
  return reducer(state, action);


import  MoMenuState  from "./mo_menu.models";
import  
  moMenuGetListAction, 
  moMenuDeleteAction,
  moMenuHttpGetListAction,
  moMenuSetListAction,
  moMenuHttpGetListErrorAction,

  moMenuGetErrorAction,
  moMenuGetIsLoadingAction,
  moMenuSetErrorAction,
  moMenuSetLoadingAction
  from "./mo_menu.actions";
import  createReducer, on, Action  from "@ngrx/store";

export const initialState: MoMenuState = 
    isLoading: false,
  HttpResponse: undefined,
MoMenuItems: null


const reducer = createReducer(
  initialState,
  on(moMenuSetErrorAction,  (state,  error ) => (
    ...state, HttpResponse:  error
  )),
   on(moMenuSetLoadingAction,  (state,  loading ) => (
    ...state, isLoading: loading 
  )),

  on(moMenuHttpGetListErrorAction, (state,  error ) => (
    undefined)),
   on(moMenuSetListAction, (state,  payload ) => (
    ...state, MoMenus: payload 
  )),

 on(moMenuHttpGetListAction, (state,  US_ID ) => (
    ...state
  )),
  on(moMenuGetListAction, state => state),
  on(moMenuDeleteAction, state => state)
);

export function moMenuReducer(
  state: MoMenuState | undefined,
  action: Action
): MoMenuState 
  return reducer(state, action);

如果你们中的一些人对我有任何想法?

【问题讨论】:

你可以为你的reducer添加代码吗? 这两个是相关的reducer 创建一个 authLoginSuccess 操作。在登录效果中登录成功时调度此操作。现在您创建了两种不同的效果,它们将监听 authLoginSuccess 操作,一种用于您的菜单,另一种用于用户信息。在每个新效果中,您将有机会调用相应的 api。有了这个,您的效果将独立工作。 【参考方案1】:

这就是我在 NgRx 8 中由于另一个操作而分派多个操作的方式:

@Injectable()
export class MyEffects 
    myAction$ = createEffect(() =>
        this.actions$.pipe(
            ofType(myActions.firstAction),
            switchMap(action => this.someService.getById(action.someId)),
            switchMap((sth: Something) => [
                myActions.firstActionSuccess( payload: sth ),
                myActions.secondAction( payload: sth.xyz ),
                // ... more actions
            ])
        )
    );

    constructor(
        private someService: SomeService,
        private actions$: Actions
    )  

动作如下所示:

export const firstAction = createAction('First Action', props< someId: number >());
export const firstActionSuccess = createAction('First Action Success', props< payload: Something >());
export const secondAction = createAction('Second Action', props< payload: string >());

希望有帮助!

【讨论】:

【参考方案2】:

您可以这样做以在效果中调度多个操作

@Effect()
    someEffect$: Observable<Action> = this.actions$.pipe(
        ofType<SOME_ACTION>(SOME_ACTION),
        switchMap(_ =>
            of(
                new myAction.Refresh(),
                new myAction.Clear()
                // another action
            )
        )
    );

还要确保有适当的效果来倾听你的动作以使其发挥作用

【讨论】:

我正在使用 ngrx 8 装饰器,不再使用,并且动作不起作用,所以我不能做新的“MYACTION”编译器说错误不能在 void 函数上使用新的。还要注意我的代码末尾的调度错误,我认为这会阻止我执行 this.store.dispatch(moMenuHttpGetListAction( US_ID : action.username ));

以上是关于ngrx 8影响其他类型的调度动作的主要内容,如果未能解决你的问题,请参考以下文章

ngrx 调度的动作未达到效果

Ngrx 一次分派一个动作多次

如何同时调度多个 ngrx 动作

在调度一个动作和 NgRx 效果之前执行多个 API 调用

如何在ngrx/effect(redux-observable)中调度多个动作?

Ngrx - 减速器无法接收动作