最终表单数组字段异步验证

Final form array fields async validation

我正在尝试实施异步验证 react-final-form-array。但是它的返回承诺却根本没有显示错误。

我参考了this code for asnyc validate and created my own version with final form array here

表格:

<Form
  onSubmit={onSubmit}
  mutators={{
    ...arrayMutators
  }}
  initialValues={{ customers: [{ placeholder: null }] }}
  validate={formValidate}
  render={({
    handleSubmit,
    mutators: { push, pop }, // injected from final-form-arrays above
    pristine,
    reset,
    submitting,
    values,
    errors
  }) => {
    return (
      <form onSubmit={handleSubmit}>
        <div>
          <label>Company</label>
          <Field name="company" component="input" />
        </div>
        <div className="buttons">
          <button type="button" onClick={() => push("customers", {})}>
            Add Customer
          </button>
          <button type="button" onClick={() => pop("customers")}>
            Remove Customer
          </button>
        </div>
        <FieldArray name="customers" validate={nameValidate}>
          {({ fields }) =>
            fields.map((name, index) => (
              <div key={name}>
                <label>Cust. #{index + 1}</label>
                <Field
                  name={`${name}.firstName`}
                  component={testInput}
                  placeholder="First Name"
                />
                <Field
                  name={`${name}.lastName`}
                  component={testInput}
                  placeholder="Last Name"
                />
                <span
                  onClick={() => fields.remove(index)}
                  style={{ cursor: "pointer" }}
                >
                  ❌
                </span>
              </div>
            ))
          }
        </FieldArray>

        <div className="buttons">
          <button type="submit" disabled={submitting || pristine}>
            Submit
          </button>
          <button
            type="button"
            onClick={reset}
            disabled={submitting || pristine}
          >
            Reset
          </button>
        </div>
        <pre>
          nameValidate Function:{"\n"}
          {JSON.stringify(nameValidate(values.customers), 0, 2)}
        </pre>
        <pre>
          Form errors:{"\n"}
          {JSON.stringify(errors, 0, 2)}
        </pre>
        <pre>
          Form values:{"\n"}
          {JSON.stringify(values, 0, 2)}
        </pre>
      </form>
    );
  }}
/>

验证函数:

const duplicateName = async value => {
  await sleep(400);
  if (
    ~["john", "paul", "george", "ringo"].indexOf(value && value.toLowerCase())
  ) {
    return { firstName: "name taken!" };
  }
};

const nameValidate = values => {
  if (!values.length) return;

  const errorsArray = [];

  values.forEach(value => {
    if (value) {
      let errors = {};

      if (!value.firstName) errors.firstName = "First Name Required";
      if (Object.keys(errors).length === 0) {
        errors = duplicateName(value.firstName);
        console.log("errors", errors);
      }
      errorsArray.push(errors);
    }
  });

  return errorsArray;
};

好的,您正在以不允许的方式混合验证。您不能在错误数组中嵌入 Promise,整个验证函数必须 return 一个 Promise。 Here's the fixed versionawait duplicateName() 是重要的一点。

const nameValidate = async values => {
  if (!values.length) return

  return await Promise.all(
    values.map(async value => {
      let errors = {}
      if (value) {
        if (!value.firstName) errors.firstName = 'First Name Required'
        if (Object.keys(errors).length === 0) {
          errors = await duplicateName(value.firstName)
        }
      }
      console.error(errors)
      return errors
    })
  )
}