为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

qq_笑_17 2023-04-27 16:37:34
减速器: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 成功时导航到成功屏幕)。是否可以等待商店中的值更新然后订阅它,或者是否有任何最佳实践来处理这种情况?一旦成功操作被分派,我可以编写一个效果来导航用户,但我的意思是,一旦标志设置为真,我确实有其他功能要处理,因此必须在组件中做所有事情。
查看完整描述

3 回答

?
aluckdog

TA贡献1847条经验 获得超7个赞

事件的顺序如下:


你发送一个AddUser动作

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

Reducer 被调用,状态被改变并被userAdded设置为false

    case ADD_USER: {

      return {

        ...state,

        userAdded: false

        }

      },

调用选择器并通知订阅者,但您还没有任何订阅

调用EffectADD_USER并将异步请求发送到userService

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

        )

      )

    )

  );

您在管道中订阅带有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');

    }

  });


查看完整回答
反对 回复 2023-04-27
?
慕姐4208626

TA贡献1852条经验 获得超7个赞

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



查看完整回答
反对 回复 2023-04-27
?
子衿沉夜

TA贡献1828条经验 获得超3个赞

我想你可以分派多个动作,你必须创建单独的动作来处理路由。


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

          ])

        )

      )

    )

  );


查看完整回答
反对 回复 2023-04-27
  • 3 回答
  • 0 关注
  • 66 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信