最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - ngrx 8 effects dispatch action of other type - Stack Overflow

programmeradmin3浏览0评论

I'm reaching you here about ngrx effects, what i am tryign to do is to have a function login that distpatch an action type login and an effect on this action will user my service to make api call. After this return token, i want to dispatch two other action one of type getUserMenu and one of type getUserInfo. Those two action will be of different type and have different effect.

I have 3 stores at the end: one for token and auth one for user info one for menu info

i tried things like that :

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 }
);

if i set dispatch false login work but no method called for getting user info and user menu but when i set dispatch true i have infinit loop on this same effect the action moMenuHttpGetListAction would look like that :

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 }
  );

but on this one when i set dispatch to true , i got error compiling. and my action looks like :

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");

those are the two reducers concerned as someone ask me to add :

Ngrx is kinda new to me so i'd love some help on this =)

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);
}

If some of you guys have any idea for me ?

I'm reaching you here about ngrx effects, what i am tryign to do is to have a function login that distpatch an action type login and an effect on this action will user my service to make api call. After this return token, i want to dispatch two other action one of type getUserMenu and one of type getUserInfo. Those two action will be of different type and have different effect.

I have 3 stores at the end: one for token and auth one for user info one for menu info

i tried things like that :

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 }
);

if i set dispatch false login work but no method called for getting user info and user menu but when i set dispatch true i have infinit loop on this same effect the action moMenuHttpGetListAction would look like that :

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 }
  );

but on this one when i set dispatch to true , i got error compiling. and my action looks like :

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");

those are the two reducers concerned as someone ask me to add :

Ngrx is kinda new to me so i'd love some help on this =)

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);
}

If some of you guys have any idea for me ?

Share Improve this question edited Aug 13, 2019 at 6:56 Razgort asked Aug 13, 2019 at 4:22 RazgortRazgort 4681 gold badge7 silver badges19 bronze badges 3
  • can you add the code for your reducer ? – Ashish Sharma Commented Aug 13, 2019 at 6:34
  • those are the two reducer concerned – Razgort Commented Aug 13, 2019 at 6:55
  • Create a authLoginSuccess action. Dispatch this action on login success in login effect. Now you create two different effect which will listen for authLoginSuccess action, one for your menu and another one for user info. In each new effect you will get chance to call respective api. With this your effects will work independently. – Suresh Muttagi Commented Aug 15, 2019 at 12:20
Add a comment  | 

2 Answers 2

Reset to default 13

This is how I'm dispatching multiple actions as a result of another action in 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
    ) { }
}

Actions look like this:

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 }>());

Hope that helps!

You can do like this to dispatch multiple action in your effect

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

Also make sure to have approriate effect that listen on your action to make it work

发布评论

评论列表(0)

  1. 暂无评论