Formik FieldArray - динамически генерировать имя - PullRequest
0 голосов
/ 12 мая 2018

Я делаю информационную форму «Основной попечитель», и есть кнопка для динамического добавления «Экстренные контакты».

Используя <FieldArray name="emergencyContacts" />, есть способ автоматически добавить префикс name<Field /> компонентов с родительским name и дочерним index, так что Formik знает, где его обновить в values?


Вот мой упрощенный код:

const DEFAULT_CAREGIVER = {
  firstName: '',
  lastName: '',
};

function ContactInfoForm({ parentName }) {

  // I have to prefix the names so that Formik updates the correct values
  // I'd like to remove this prefix logic, and hopefully use existing properties:
  // "This component is rendered within a <FieldArray name="emergencyContacts" />"
  function prefix(name) {
    return parentName ? `${parentName}.${name}` : name;
  }

  return (
    <React.Fragment>
      <Field
        component={TextField}
        id="firstName"
        label="First Name"
        name={prefix('firstName')}
        required
      />
      <Field
        component={TextField}
        id="lastName"
        label="Last Name"
        name={prefix('lastName')}
        required
      />
    </React.Fragment>
  );
}

function CaregiverForm({ name }) {
  return (
    // I'm hoping to not have to pass the prefix path along
    // We have lots of reusable components in this form
    <ContactInfoForm parentName={name} />
  );
}

class PrimaryCaregiverForm extends React.Component {
  renderEmergencyContacts = fieldArray => {
    const { values } = this.props;

    return (
      <React.Fragment>
        {values.emergencyContacts.length > 0 &&
          values.emergencyContacts.map((contact, index) => (
            <div key={index}>
              <PageTitle>Emergency Contact {index + 1}</PageTitle>
              <CloseButton onClick={() => fieldArray.remove(index)} />
              <CaregiverForm
                name={`${fieldArray.name}.${index}`}
                {...this.props}
              />
            </div>
          ))}
        <AddEmergencyContactButton
          onClick={() => fieldArray.push(DEFAULT_CAREGIVER)}
        />
      </React.Fragment>
    );
  };

  render() {
    const { handleSubmit } = this.props;
    return (
      <Form onSubmit={handleSubmit}>
        <PageTitle>Primary Caregiver</PageTitle>
        <CaregiverForm {...this.props} />
        <FieldArray
          name="emergencyContacts"
          render={this.renderEmergencyContacts}
        />
        <Button type="submit">Save & Continue</Button>
      </Form>
    );
  }
}

const caregiverValidationSchema = {
  firstName: Yup.string().required('First name is required.'),
  lastName: Yup.string().required('Last name is required.'),
};

const PrimaryCaregiverPage = withFormik({
  mapPropsToValues: () => ({
    ...DEFAULT_CAREGIVER,
    emergencyContacts: [],
  }),
  validationSchema: Yup.object().shape({
    ...caregiverValidationSchema,
    emergencyContacts: Yup.array().of(
      Yup.object().shape(caregiverValidationSchema),
    ),
  }),
})(PrimaryCaregiverForm);
...