Redux-Form в функциональном Reactjs компоненте - mapStateToProps использует предыдущие реквизиты - PullRequest
0 голосов
/ 15 апреля 2020

Я сижу здесь часами и не могу найти решение. Ниже вы видите функциональный компонент React в сочетании с Redux и Redux-Form. Компонент имеет необязательную опору "note".

Теперь моя проблема: когда я вызываю компонент первым с примечанием, как показано ниже

<NoteForm note={...}></NoteForm>

все в порядке - mapStateToProps извлекает примечание из ownProps и вставляет значения в начальные значения.

Но если я назову этот компонент где-нибудь еще без примечание после , я назвал его с a примечание как ниже

<NoteForm></NoteForm>

ownProps внезапно содержит все еще примечание от прежнего рендеринга. Компонент, кажется, не принимает «неопределенное» в качестве триггера для смены реквизита в новом жизненном цикле, если примечание было предоставлено ранее.

У кого-нибудь есть идея?

Пожалуйста, найдите весь компонент ниже

import React, { FC, useCallback, useState } from 'react';
...

interface RFInProps {
  closeForm: () => void;
  note?: ListNote;
  saveNote: (title: string, content: string, shareWithSubject: boolean) => Promise<ThunkAnyAction<ListNote>>;
}

type OwnProps = RFInProps & InjectedFormProps<UpdateNoteFormValues, RFInProps>

const NoteForm: FC<OwnProps> = (props) => {
  const [t] = useTranslation();
  const formHeadline = props.note ? 'x.notes.edit' : 'x.notes.new';
  const [errors, setErrors] = useState<Record<string, NoteAPIError[]>>({});

  ...

  const renderInput = useCallback(({ input, label, type, meta: { error, touched } }: FieldType) => (
    <CustomFormInput
      { ...input }
      label={ label }
      labelKey={ label }
      type={ type }
      error={ touched ? error : undefined }
    />
  ), [props.note]);

  const renderTextarea = useCallback(
    ({ input, translationKey, label, meta: { error, touched } }: FieldType) => (
      <CustomTextArea
        { ...input }
        translationKey={ translationKey }
        error={ touched ? error : null }
        label={ label }
        labelKey="x.notes.content"
        minHeight={ 60 }
        autoExpand
      />
    ),
    [props.note],
  );

  const renderCheckBox = useCallback(
    ({ input, label }) => (
      <CheckBox
        { ...input }
        label={ label }
      />
    ),
    [props.note],
  );

  const renderValidationError = (field: string, err: NoteAPIError) => (
    <div>
      { field }:
      { t('x.error.' + err.type) }
      { err.args && ' (' + Object.keys(err.args)
        .map((argKey) => `${ t(`x.error.${ argKey }`) }: ${ err.args[ argKey ] }`)
        .join(', ') + ')'
      }
    </div>
  );

  return (
    <NoteFormContainer>
      <form onSubmit={ props.handleSubmit(submit) } noValidate>
          ...
          <Field
            name="content"
            label={ t('x.notes.content') }
            component={ renderTextarea }
            validate={ [validatorRequired] }
          />
        ...
      </form>
    </NoteFormContainer>
  );
};

const mapStateToProps = (_: StoreI, ownProps: RFInProps) => ( {
  initialValues: {
    title: ownProps.note ? ownProps.note.title : '',
    content: ownProps.note ? ownProps.note.content : '',
    share_with_subject: ownProps.note ? ownProps.note.share_with_subject : false,
  },
} );

// Ignore because reduxForm accepts a second argument indeed
const NoteFormRF = connect(mapStateToProps, null)(reduxForm<UpdateNoteFormValues, RFInProps>({
  form: 'noteForm',
  destroyOnUnmount: true,
  forceUnregisterOnUnmount: true,
})(NoteForm));
export default NoteFormRF;
...