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

use*_*206 5 javascript yup react-hook-form

我有一个 onChange 函数onNameChange,其中包含一个valid应与名称字段的 yup 验证相匹配的变量。问题在于,有效变量仅在提交表单后才显得正确,而在更改名称字段时则不然;我希望在提交之前该信息有效。

如何在更改名称字段而不是提交时获得正确的值?请注意,我发现了类似的帖子,但使用了 Formik,这不是我想要使用的:Formik + 是的:如何在提交之前立即验证表单?

是的设置:

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"
  });
Run Code Online (Sandbox Code Playgroud)

改名功能:

  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);
  };
Run Code Online (Sandbox Code Playgroud)

演示形式:

<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>
Run Code Online (Sandbox Code Playgroud)

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

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

谢谢

kno*_*fel 7

问题是您在更改 name 后没有更新 RHF 状态<input />,因为您正在覆盖onChange{...register('name')}.

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

  1. 用于更新回调内部的setValueRHF 状态值nameonNameChange
  2. 使用<Controller />组件

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

这将如何使用第二个选项来实现<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>
Run Code Online (Sandbox Code Playgroud)

编辑 React PlayGround(分叉)