Yup & React Hook Form:如何验证 onChange 而不是 onSubmit

Yup & React Hook Form: How to validate onChange rather than onSubmit

我有一个 onChange 函数 onNameChange,它包含一个 valid 变量,该变量应该与名称字段的 yup 验证相匹配。问题是 valid 变量似乎只有在提交表单后才是正确的,而不是在更改名称字段时;我希望它在提交之前有效。

如何在更改名称字段而不是提交时获得正确的值?请注意,我发现了一个类似的 post 但它使用了 Formik,这不是我想要使用的:

Yup 设置:

const schema = Yup.object().shape({
    name: Yup.string()
      .required("Required")
      .min(3, "Enter at least 3 characters")
  });
  const {
    register,
    handleSubmit,
    setError,
    formState: { errors },
    trigger
  } = useForm({
    resolver: yupResolver(schema)
    // mode: "onTouched",
    // reValidateMode: "onChange"
  });

改名功能:

  const onNameChange = async ({ target: { value } }) => {
    const valid = await trigger("name");
    console.log("valid", valid, "value", value);
    if (!valid) {
      // @todo: bug here? valid only correct after submitting
      return;
    }
    getPokemon(value);
    setShowPokemon(false);
  };

演示形式:

<form onSubmit={handleSubmit(onSubmit /*, onError*/)}>
        <input
          {...register("name", { required: true })}
          name="name"
          placeholder="Enter a pokemon"
          onChange={onNameChange}
        />
        <button type="submit" onClick={onSubmit}>
          Show Pokemon
        </button>
        {errors.name && <p>{errors.name.message}</p>}
      </form>

我在 codesandbox 上做了一个现场演示,应该会有帮助:

https://codesandbox.io/s/react-playground-forked-odwi2?file=/Pokemon.js

谢谢

问题是您在更改名称 <input /> 后没有更新 RHF 状态,因为您覆盖了从 {...register('name')} 返回的 onChange 属性。

所以基本上你必须在这里选择:

  1. 使用 setValueonNameChange 回调
  2. 中更新 name 的 RHF 状态值
  3. 使用<Controller />组件

您可以在 GitHub 上的 discussion 中阅读相关内容。

第二个选项的实现方式 <Controller />:

<form onSubmit={handleSubmit(onSubmit /*, onError*/)}>
  <Controller
    name="name"
    control={control}
    defaultValue=""
    render={({ field: { value, onChange, ...field } }) => (
      <input
        {...field}
        onChange={({ target: { value } }) => {
          onChange(value);
          onNameChange(value);
        }}
        placeholder="Enter a pokemon"
      />
    )}
  />

  <button type="submit" onClick={onSubmit}>
    Show Pokemon
  </button>
  {errors.name && <p>{errors.name.message}</p>}
</form>