gpt4 book ai didi

angular - ngrx 链接 Action /效果 - 例如登录然后导航

转载 作者:太空狗 更新时间:2023-10-29 17:05:14 24 4
gpt4 key购买 nike

我是 ngrx 和 Redux 风格架构的新手,我在理解应该如何链接操作/效果时遇到问题。一个例子是实现基本功能,例如在用户登录后采取行动。我在这里的核心问题是,在用户登录后要采取的行动将根据应用程序的当前状态而有所不同——用户可能在任何地方在出现登录提示/页面时出现在应用程序中。

我见过的任何示例都会在用户登录后发生硬编码效果。在我的场景中,这并不适合如上所述,我并不总是希望发生相同的操作。

以下是包含登录组件的主页的一些示例代码。在这种情况下,我希望用户在登录后被重定向到“/buy”。

@Component(..)
export class HomePageComponent {
constructor(private store: Store<any>) {
}

public onLoginSubmitted(username, password) {
this.store.dispatch(new loginActions.Login({username, password}));
// once this has happened successfully navigate to /buy
}

}

示例效果

@Injectable()
export class LoginEffects {

......

@Effect()
login$ = this.actions$
.ofType(loginActions.ActionTypes.LOGIN)
.switchMap((data) => {
return this.loginService.login(data.payload)
.map(() => new loginActions.LoginSuccess({loggedIn: true, isLoggingIn: false}))
.catch((error) => {
return of(new loginActions.LoginError({loggedIn: false, isLoggingIn: false}));
});
});
......
}

关于您如何解决这个问题,我有几个想法 - 但没有一个是正确的。这些包括

  • 通过登录负载传递数据以确定接下来要采取的操作
  • 编写大量效果,这些效果在 LoginSuccess 时执行,但在更高级别进行过滤
  • 通过监听商店中的事件来编写组件特定效果(这可能/不好的做法吗?)
  • 从商店中读取有关当前登录状态的数据并在组件中对此进行操作。但是这个逻辑会立即运行,可能不会达到预期的效果

任何人都可以指出正确的道路/举例说明应该如何解决这个问题吗?

最佳答案

使用 mergeMap 对一组 Action ,一个效果可以触发多个 Action 。我通常会做的是,传递我希望登录效果也分派(dispatch)的附加操作。

@Component(..)
export class HomePageComponent {
constructor(private store: Store<any>) { }

public onLoginSubmitted(username, password) {
this.store.dispatch(new loginActions.Login({
username,
password,
onCompleteActions: [new loginActions.Redirect({ route: '/buy' })] }));
}
}

然后,登录效果将使用 mergeMap 分派(dispatch)任何传入的操作。您仍然需要为每个操作创建效果,但现在您可以构建更多可重复使用的操作,例如重定向操作。

@Injectable()
export class LoginEffects {

......

@Effect()
login$ = this.actions$
.ofType(loginActions.ActionTypes.LOGIN)
.switchMap((data) => {
let mappedActions = [new loginActions.LoginSuccess({loggedIn: true, isLoggingIn: false})];
if (data.payload.onCompleteActions)
mappedActions = mappedActions.concat(data.payload.onCompleteActions);

return this.loginService.login(data.payload)
.mergeMap(mappedActions)
.catch((error) => {
return of(new loginActions.LoginError({loggedIn: false, isLoggingIn: false}));
});
});

......
}

我喜欢这个解决方案的一点是它可以扩展到 future ,因为可以传入任何操作,并且没有开关或 if-else 树来决定要做什么。您还可以传入多个操作,因此无需构建“redirectAndCloseModal”操作,您可以传入 redirect 以及 closeModal

this.store.dispatch(new loginActions.Login({
username,
password,
onCompleteActions: [new loginActions.Redirect({ route: '/buy' }), new modalActions.CloseModal()] }));

您可以阅读更多关于 dispatching multiple Actions from one @Effect() at this github issue. 的内容

编辑:关于您的评论,不仅仅是路由更改可能会让您想要停止登录,它可能是任何东西,例如关闭模式,并且没有通用的方法来监视那。您可以向您的商店添加一些东西,例如 runLoginActions bool 值,然后在登录请求返回后从您的商店中读取该数据。

然后在您的 login$ 效果中,您可以从商店中读取它来决定是否运行其他操作。

@Effect()
login$: Observable<Action> = this.actions$
.ofType(auth.actionTypes.LOGIN)
.map((action: auth.LoginAction) => action.payload)
.switchMap((user) => {
let successAction = new loginActions.LoginSuccess({loggedIn: true, isLoggingIn: false});
let mappedActions = [successAction];
if (data.payload.onCompleteAction)
mappedActions.push(data.payload.onCompleteAction);

return this.authService.login(user.username, user.password)
.withLatestFrom(this.store)
.mergeMap(([result, store]) => store.runLoginActions ?
[mappedActions] :
[successAction]
)
.catch((err) => {
try {
return of(new auth.NetworkFailureAction(err[0].code));
} catch (e) {
throw `Array not in the expected format of [{ code: "", message: "" }]`;
}
});
});

请注意,在你的 loginSuccess reducer 中,你应该设置你的 runLoginActions = true,它应该默认为 true,只有在路由时才关闭被更改,或者组件被销毁。

请记住,这是一个通用的解决方案,您将需要自己添加操作、更新您的 reducer 等。

这更像是一个手动过程,但由于您不想执行操作的情况非常具体,因此可能必须以这种方式完成。

关于angular - ngrx 链接 Action /效果 - 例如登录然后导航,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42373191/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com