首页 > 解决方案 > 通过 ngrx 操作传递回调是一种不好的做法吗

问题描述

考虑以下情况:动作成功必须关闭模态框。这是否是一个可行的解决方案:

@Component({
  selector: 'user-delete-dialog',
  templateUrl: './user-delete-dialog.component.html',
  styleUrls: ['./user-delete-dialog.component.scss']
})
export class UserDeleteDialogComponent implements OnInit {
  @Input() user: User;

  constructor(
    public dialog: NgbActiveModal,
    private store: Store
  ) { }

  ngOnInit(): void {
  }

  confirm() {
    this.store.dispatch(
      deleteUser({ 
        id: this.user.id, 

        onComplete: () => {
          this.dialog.close();
        },
  
        onError: () => {
          // Show errors ...
        }
      })
    );
  }
}

另一种方法是订阅主 Actions 流,但仅在模式的生命周期内全局收听特定于上下文的操作感觉不对:

[...]
import { Actions } from '@ngrx/effects';
[...]

@Component(...)
class SomeComponent implements OnDestroy {
    destroyed$ = new Subject<boolean>();

    constructor(updates$: Actions) {
        updates$.pipe(
           ofType(UserActions.DELETE_SUCCESS),
           takeUntil(this.destroyed$)
        )
        .subscribe(() => {
           // close modal
        });
    }

    ngOnDestroy() {
        this.destroyed$.next(true);
        this.destroyed$.complete();
    }

    confirm() {
     this.store.dispatch(deleteUser({ id: this.user.id  }));
    }
}

有任何想法吗?

标签: angularngrx

解决方案


最佳实践是在中央减速器中收听动作。状态仅在 reducer 中更改,组件使用选择器监听状态更改。

假设您有一个 UserState 类,它有一个名为 dialogOpen 的布尔属性。创建一个名为 user.reducer.ts 的文件,其中包含以下内容

export const userReducer = createReducer<UserState>(initialState,
 on(UserActions.DELETE, (state) : UserState => { // code to delete the user}),
 on(UserActions.DELETE_SUCCESS, (state) : UserState => { // code when the delete is successful
     return {...state, dialogOpen: false}
 }),
 on(UserActions.DELETE_ERROR, (state): UserState => {/ code when the delete is errored})
)

在 DELETE_SUCCESS 上,您可以在用户状态中设置一个布尔值,例如 dialogOpen = false 并使用选择器在模态组件中检查它。

const getUserState = createFeatureSelector<UserState>('users')
export const getDialogOpen = createSelector(getUserState, state=> state.dialogOpen)

在模态组件中,您将拥有类似这样的内容

dialogOpen : Observable<boolean> = this.store.select(getDialogOpen);

推荐阅读