如何停止 ngrx-forms 重新初始化操作?

How to stop ngrx-forms reinitializing actions?

[此题基于https://ngrx-forms.readthedocs.io/]

我的 angular 组件中有一组主题(字符串)。我使用 ngrx-store 来管理状态,同时使用 ngrx-forms 来管理表单。 在组件初始化期间,我为组件内部的每个主题调度了一些操作。


 ngOnInit(): void {
    this.formState$ = this.store.pipe(select(s => s.filterByTopics.formState))
    this.topicsOptions$ = this.store.pipe(select(s => s.filterByTopics.topicsOptions))
    Object.keys(this.topics).forEach(topic => this.store.dispatch(new CreateTopicControlAction(topic)))
  }

效果很好,正在添加 ngrx 表单控件。

但真正的问题是,如果我再次访问同一个组件,它会重新初始化操作(因为 ngOnInit 包含所有操作)并吐出一个错误:

Uncaught Error: Group 'filterByTopicsForm.topics' already has child control '0'!

image.png

我怎样才能避免这种情况?

还有其他解决方法吗?

这里是 ngrx-forms 的作者。

这不是 ngrx-forms 本身的问题,而是一个更普遍的问题,即当状态在存储中时如何防止双重初始化,因此不耦合到组件的生命周期。

我在这里看到多个选项:

  1. 通过分派具有初始值的 SetValueActionResetAction 来重置 ngOnDestroy 中的表单(或创建您自己的自定义操作以重新创建在减速器中形成状态);这模拟了 @angular/forms 的行为,其中表单仅在拥有组件时存在;这是使用 ngrx v8+ 的自定义操作的样子:

    const resetMyForm = createAction('MY_FORM/reset');
    
    const myFormReducer = createReducer(
      {
        formState: createFormGroupState('MY_FORM', INITIAL_FORM_VALUE),
      },
      onNgrxForms(),
      on(resetMyForm, ({ formState }, { lang, code }) => ({
        formState: createFormGroupState('MY_FORM', INITIAL_FORM_VALUE),
      })),
    );
    
  2. 检查表单是否已经在组件中初始化

    ngOnInit(): void {
      this.formState$ = this.store.pipe(select(s => s.filterByTopics.formState))
      this.topicsOptions$ = this.store.pipe(select(s => s.filterByTopics.topicsOptions))
      Object.keys(this.topics).forEach(topic => {
        this.formState$.pipe(take(1)).subscribe(formState => {
          // how exactly this `if` looks like depends on your concrete form state shape
          if (!formState.controls.topics.controls[topic]) {
            this.store.dispatch(new CreateTopicControlAction(topic))
          }
        })
      })
    }
    
  3. 检查表单是否已经在reducer中初始化

    const createTopicControl = createAction('MY_FORM/createTopicControl', (topic: string) => ({ topic }));
    
    const myFormReducer = createReducer(
      {
        formState: createFormGroupState('MY_FORM', INITIAL_FORM_VALUE),
      },
      onNgrxForms(),
      on(createTopicControl, (state, { topic }) => {
        if (state.formState.controls.topics.controls[topic]) {
          return state
        }
    
        // add form control ...
      }),
    );
    

希望对您有所帮助。