Как остановить действия по повторной инициализации ngrx-форм? - PullRequest
1 голос
/ 22 апреля 2020

[этот вопрос основан на https://ngrx-forms.readthedocs.io/]

У меня есть массив тем (строк) внутри моего angular компонента. Я использую ngrx-store для управления состоянием вместе с ngrx-формами для управления формами. Во время инициализации компонента я отправляю некоторые действия для каждого topi c внутри компонента.


 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-form.

Но реальная проблема заключается в том, что, если я снова посещаю тот же компонент, он повторно инициализирует действия (поскольку ngOnInit содержит все действия) и выдает ошибку:

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

image.png

Как я могу предотвратить это?

Есть ли другой обходной путь?

1 Ответ

1 голос
/ 22 апреля 2020

Автор ngrx-форм здесь.

Это не проблема с ngrx-форм как таковая, но более общий вопрос о том, как предотвратить двойной инициализация, когда состояние находится в хранилище, и, следовательно, не связано с временем жизни компонента.

Я вижу несколько вариантов здесь:

  1. сбросить форму в ngOnDestroy путем отправки SetValueAction с начальным значением, а также ResetAction (или создайте свое собственное настраиваемое действие для воссоздания состояния формы в редукторе); это эмулирует поведение @ 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. Проверьте, не инициализирована ли уже форма в редукторе

    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 ...
      }),
    );
    

Надеюсь, это поможет.

...