猿问

如何显示成功消息 NgRX Effects 和调度事件

减速器:


export const reducer = (state = initialstate, action: any) => {

  switch (action.type) {

    case ADD_USER: {

      return {

        ...state,

        userAdded: false

        }

      },

    case ADD_USER_SUCCESS: {

      return {

        ...state,

        user: action.payload

        userAdded: true

        }

      },

    case ADD_USER_FAIL: {

      return {

        ...state,

        userAdded: false

        }

      }  

    }

}

影响:


login$ = createEffect(() =>

    this.actions$.pipe(

      ofType(UserAction.ADD_USER),

      exhaustMap(action =>

        this.userService.addUser("USER").pipe(

          map(user => UserAction.AddUserSuccess({ "user" })),

          catchError(error => of(UserAction.AddUserFail({ error })))

        )

      )

    )

  );

组件.ts:


onClickAddUser(): void {

  this.store.dispatch(new AddUser('USER'));

  this.store.pipe(select(getUser), take(1)).subscribe((isUserAdded) => {

    if(isUserAdded) {

      this.router.navigateByUrl('/success'); // Expectation is to navigate to success page

    } else {

      this.router.navigateByUrl('/home'); // for first time it's always going to home screen even the success action being dispatched and the value been set to true.

    }

  });

}

单击该方法时,将分派一个动作并跟进一个效果,我的情况是 api 调用成功并且也分派了一个成功的动作(在我的 reducer 中我将标志设置为 true),紧接在 AddUser 动作之后从 click 方法发送,如果 API 返回成功响应,我订阅标志以将用户导航(isUserAdded)到屏幕,在我的情况下,当我订阅标志时,它没有在商店中更新,因此用户导航/success到主屏幕(但期望是在 API 成功时导航到成功屏幕)。是否可以等待商店中的值更新然后订阅它,或者是否有任何最佳实践来处理这种情况?


一旦成功操作被分派,我可以编写一个效果来导航用户,但我的意思是,一旦标志设置为真,我确实有其他功能要处理,因此必须在组件中做所有事情。


qq_笑_17
浏览 104回答 3
3回答

aluckdog

事件的顺序如下:你发送一个AddUser动作this.store.dispatch(new AddUser('USER'));Reducer 被调用,状态被改变并被userAdded设置为false    case ADD_USER: {      return {        ...state,        userAdded: false        }      },调用选择器并通知订阅者,但您还没有任何订阅调用EffectADD_USER并将异步请求发送到userServicelogin$ = createEffect(() =>    this.actions$.pipe(      ofType(UserAction.ADD_USER),      exhaustMap(action =>        this.userService.addUser("USER").pipe(          map(user => UserAction.AddUserSuccess({ "user" })),          catchError(error => of(UserAction.AddUserFail({ error })))        )      )    )  );您在管道中订阅带有getUser运算符的选择器take(1)  this.store.pipe(select(getUser), take(1)).subscribe((isUserAdded) => {    if(isUserAdded) {      this.router.navigateByUrl('/success');    } else {      this.router.navigateByUrl('/home');    }  });userAdded选择器从商店返回标志的值false,您的回调函数被调用,订阅被take(1)运营商取消路由器导航到“/home”来自的响应userService已返回且userAdded标志设置为true但您的订阅已被取消如果您想要一个简单的解决方案component.ts,只需尝试订阅take(2), skip(1):  this.store.pipe(select(getUser), take(2), skip(1)).subscribe((isUserAdded) => {    if(isUserAdded) {      this.router.navigateByUrl('/success');    } else {      this.router.navigateByUrl('/home');    }  });

慕姐4208626

你不能只在你的效果 fn 中返回两个动作,比如 UserAddedSuccess 并在 catchError UserAddedFail 中写另一个效果,它将监听 useraddedsuccess 动作并在成功时重定向所需的页面,在第一个效果 catcherror 返回 UserAddedFail 动作和相同的过程?

子衿沉夜

我想你可以分派多个动作,你必须创建单独的动作来处理路由。login$ = createEffect(() =>    this.actions$.pipe(      ofType(UserAction.ADD_USER),      exhaustMap(action =>        this.userService.addUser("USER").pipe(          switchMap(user => [            UserAction.AddUserSuccess({ "user" }),            routeAction.routeto('success')          ])          ,catchError(error => [            UserAction.AddUserFail({ error }),            routeAction.routeto('Home');          ])        )      )    )  );
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答