Angular 9 + NGRX:在组件中捕获效果完成的最佳方式
Angular 9 + NGRX: Best way to catch effect completion in component
我有一个要创建的表单和帐户:电子邮件、姓名、密码...我希望该应用程序在创建成功时向用户显示一条消息,更准确地说,当效果创建告诉用户的操作时已创建用户。
- 提交用户创建表单后,我将表单内容发送到商店并执行操作。
- 我在调度该操作时触发了效果。
- 效果是在我的后端调用一个在数据库中创建帐户的 http api 服务。
- 当服务完成后,效果会派发一个新的动作'UserCreated'
我的问题是:告诉组件用户已正确创建的最佳方式是什么?
目前我这样做了:
当服务完成后调用 UserCreated 操作时,我使用新创建的用户的 ID 更新商店。
我在 ngOnInit 中订阅了一个发送 id 值的选择器:如果它不为空,我会显示一条消息。
我觉得这不是最好的方法:我想避免为使用选择器的商店设置 id(或布尔值 true/false)。
我希望组件订阅 action: UserCreated 而不是,我觉得这样更干净(我也可能想错了)。
我看过一些关于操作订阅的帖子,但它对我不起作用(这些帖子与旧版本的 angular 相关,方法不再存在)。
提交表格:createaccount.component.ts
this.store.dispatch(new UserServerCreation({ user: _user }));
createaccount.action.ts
export class UserServerCreation implements Action {
readonly type = UserActionTypes.UserServerCreation;
constructor(public payload: { user: User }) { }
createaccount.effects.ts
@Effect()
createUser$ = this.actions$
.pipe(
ofType<UserServerCreation>(UserActionTypes.UserServerCreation),
mergeMap(({ payload }) => {
return this.userService.createUser(payload.user).pipe(
tap(res => {
this.store.dispatch(new UserCreated({ user: res.payload }));
}),
catchError(error => {
this.snackBar.open(this.translateService.instant(error.error.errors.message), 'Error', {
duration: 5000,
});
return of([]);
}),
);
}),
);
createaccount.selector.ts
export const selectLastCreatedUserId = createSelector(
selectUsersState,
usersState => usersState.lastCreatedUserId
);
createaccount.component.ts
中的选择器订阅
ngOnInit() {
this.store.pipe(select(selectLastCreatedUserId)).subscribe(newId => {
console.log('ID: ' + newId);
if (newId) {
const message = this.translateService.instant('USER.CREATED');
this.layoutUtilsService.showActionNotification(message, MessageType.Create, 5000, true, false);
this.userForm.reset();
}
});
}
更新解决方案:
终于实现订阅action channel(这是我在效果上比snackbar更喜欢的方法)
在我的 createaccount.component.ts 上,我添加了这些样本:
变量:
destroy$ = new Subject<boolean>();
在构造函数中:
private actionsListener$: ActionsSubject
然后在 ngOnInit 中:
this.actionsListener$
.pipe(ofType(UserActionTypes.LoginOnDemandCreated))
.pipe(takeUntil(this.destroy$))
.subscribe((data: any) => {
// Do your stuff here
console.log('DATA : ' + JSON.stringify(data)); //Just for testing purpose
});
终于在 ngOnDestroy 中:
ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.complete();
}
感谢您的帮助!
我知道两种方式:
- 使用
{ dispatch: false }
创建另一个效果,这意味着该效果不会发送任何操作,但可以执行一些逻辑操作,例如打开 Snackbar。 (ofType<UserServerCreated (UserActionTypes.UserServerCreated)
) 并简单地添加一个 tap
运算符函数,并执行与 catchError
. 中相同的操作
- 您还可以将您的组件订阅到操作的频道。所以你可以像在效果器中一样过滤这个通道。并像以前一样执行相同的逻辑,或者保存它并在组件中执行一条消息。
试试这个
stateSubscription: any;
this.stateSubscription = this.store.dispatch(new UserServerCreation({ user: _user }));
this.stateSubscription = this.store.pipe(select(fromAppLanguage.selectPageState)).subscribe((data) => {
if (data && data != undefined) {
if (data['code'] == 200) {
console.log('---success')
this.userForm.reset();
} else {
console.log('---err')
this.toastr.error(data['message']);
this.stateSubscription.unsubscribe();
}
}
});
我有一个要创建的表单和帐户:电子邮件、姓名、密码...我希望该应用程序在创建成功时向用户显示一条消息,更准确地说,当效果创建告诉用户的操作时已创建用户。
- 提交用户创建表单后,我将表单内容发送到商店并执行操作。
- 我在调度该操作时触发了效果。
- 效果是在我的后端调用一个在数据库中创建帐户的 http api 服务。
- 当服务完成后,效果会派发一个新的动作'UserCreated'
我的问题是:告诉组件用户已正确创建的最佳方式是什么?
目前我这样做了:
当服务完成后调用 UserCreated 操作时,我使用新创建的用户的 ID 更新商店。
我在 ngOnInit 中订阅了一个发送 id 值的选择器:如果它不为空,我会显示一条消息。
我觉得这不是最好的方法:我想避免为使用选择器的商店设置 id(或布尔值 true/false)。
我希望组件订阅 action: UserCreated 而不是,我觉得这样更干净(我也可能想错了)。
我看过一些关于操作订阅的帖子,但它对我不起作用(这些帖子与旧版本的 angular 相关,方法不再存在)。
提交表格:createaccount.component.ts
this.store.dispatch(new UserServerCreation({ user: _user }));
createaccount.action.ts
export class UserServerCreation implements Action {
readonly type = UserActionTypes.UserServerCreation;
constructor(public payload: { user: User }) { }
createaccount.effects.ts
@Effect()
createUser$ = this.actions$
.pipe(
ofType<UserServerCreation>(UserActionTypes.UserServerCreation),
mergeMap(({ payload }) => {
return this.userService.createUser(payload.user).pipe(
tap(res => {
this.store.dispatch(new UserCreated({ user: res.payload }));
}),
catchError(error => {
this.snackBar.open(this.translateService.instant(error.error.errors.message), 'Error', {
duration: 5000,
});
return of([]);
}),
);
}),
);
createaccount.selector.ts
export const selectLastCreatedUserId = createSelector(
selectUsersState,
usersState => usersState.lastCreatedUserId
);
createaccount.component.ts
中的选择器订阅ngOnInit() {
this.store.pipe(select(selectLastCreatedUserId)).subscribe(newId => {
console.log('ID: ' + newId);
if (newId) {
const message = this.translateService.instant('USER.CREATED');
this.layoutUtilsService.showActionNotification(message, MessageType.Create, 5000, true, false);
this.userForm.reset();
}
});
}
更新解决方案:
终于实现订阅action channel(这是我在效果上比snackbar更喜欢的方法)
在我的 createaccount.component.ts 上,我添加了这些样本: 变量:
destroy$ = new Subject<boolean>();
在构造函数中:
private actionsListener$: ActionsSubject
然后在 ngOnInit 中:
this.actionsListener$
.pipe(ofType(UserActionTypes.LoginOnDemandCreated))
.pipe(takeUntil(this.destroy$))
.subscribe((data: any) => {
// Do your stuff here
console.log('DATA : ' + JSON.stringify(data)); //Just for testing purpose
});
终于在 ngOnDestroy 中:
ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.complete();
}
感谢您的帮助!
我知道两种方式:
- 使用
{ dispatch: false }
创建另一个效果,这意味着该效果不会发送任何操作,但可以执行一些逻辑操作,例如打开 Snackbar。 (ofType<UserServerCreated (UserActionTypes.UserServerCreated)
) 并简单地添加一个tap
运算符函数,并执行与catchError
. 中相同的操作
- 您还可以将您的组件订阅到操作的频道。所以你可以像在效果器中一样过滤这个通道。并像以前一样执行相同的逻辑,或者保存它并在组件中执行一条消息。
试试这个
stateSubscription: any;
this.stateSubscription = this.store.dispatch(new UserServerCreation({ user: _user }));
this.stateSubscription = this.store.pipe(select(fromAppLanguage.selectPageState)).subscribe((data) => {
if (data && data != undefined) {
if (data['code'] == 200) {
console.log('---success')
this.userForm.reset();
} else {
console.log('---err')
this.toastr.error(data['message']);
this.stateSubscription.unsubscribe();
}
}
});