【问题标题】:'isValid' is always false'isValid' 总是假的
【发布时间】:2020-10-13 09:21:12
【问题描述】:

我在react-hook-form 中使用自定义register,当我在输入中输入文本时,我无法将formState.isValid 变为true(因此满足required 条件)。

这是一个示例代码:

interface FormValues {
  readonly value: string;
}

export default function App() {
  console.log("rendering");

  const form: UseFormMethods<FormValues> = useForm<FormValues>({
    mode: "onChange",
    reValidateMode: "onChange",
    defaultValues: { value: "" }
  });

  useEffect(() => {
    form.register({ name: "value" }, { required: true });
  }, [form, form.register]);

  const { isValid } = form.formState;
  const value = form.watch("value");

  return (
    <div>
      <input
        onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
          form.setValue("value", e.target.value);
        }}
      />
      <div>IsValid: {JSON.stringify(isValid)}</div>
      <div>Errors: {JSON.stringify(form.errors)}</div>
      <div>Value: {JSON.stringify(value)}</div>
    </div>
  );
}

问题是针对这种类型的register 使用,而不是其他类型(refController)。

Here 是一个完整的例子。

有人知道为什么会这样,我错过了什么吗?

另外,但这不太相关 - 有谁知道为什么每次输入更改都会触发两次渲染?

编辑

与丹尼斯·瓦什讨论后,在这个问题上取得了一些进展,但仍未解决。

https://react-hook-form.com/api/#setValue 的文档实际上确实指定了触发验证的选项:

(name: string, value: any, shouldValidate?: boolean) => void


You can also set the shouldValidate parameter to true in order to trigger a field validation. eg: setValue('name', 'value', true)

在我写这篇文章的时候,文档引用了react-form-hook 的第 5 版,我实际上使用的是6.0.0-rc.5,所以签名有点类似于以下内容:

(name: string, value: any, { shouldValidate: boolean; shouldDirty: boolean; }) => void

但是,在我使用 shouldValidate: true 时的示例中,我得到了一个无限循环:

interface FormValues {
  readonly value: string;
}

export default function App() {
  console.log("rendering");

  const form: UseFormMethods<FormValues> = useForm<FormValues>({
    mode: "onChange",
    reValidateMode: "onChange",
    defaultValues: { value: "" }
  });

  useEffect(() => {
    form.register({ name: "value" }, { required: true, minLength: 1 });
  }, [form, form.register]);

  const { isValid } = form.formState;
  const value = form.getValues("value");

  return (
    <div>
      <input
        onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
          form.setValue("value", e.target.value, {
            shouldValidate: true
          });
        }}
      />
      <div>IsValid: {JSON.stringify(isValid)}</div>
      <div>Errors: {JSON.stringify(form.errors)}</div>
      <div>Value: {JSON.stringify(value)}</div>
    </div>
  );
}

循环在isValidtrue 时发生,但在false 时停止。

你可以试试here。输入一个键会开始不断的重新渲染,清除输入会停止循环...

【问题讨论】:

    标签: reactjs react-hook-form


    【解决方案1】:

    组件因为React.StrictMode而渲染了两次。

    严格模式无法自动为您检测副作用,但可以通过使它们更具确定性来帮助您发现它们。这是通过有意双重调用以下函数来完成的:...

    另外,为了验证您需要提交表单(尝试按enter),如果您在onChange 模式下不使用参考,您应该使用triggerValidation

    export default function App() {
      const {
        register,
        formState,
        watch,
        errors,
        setValue,
        handleSubmit
      }: UseFormMethods<FormValues> = useForm<FormValues>();
    
      useEffect(() => {
        register(
          { name: "firstName", type: "custom" },
          { required: true, min: 1, minLength: 1 }
        );
        console.log("called");
      }, [register]);
    
      const { isValid } = formState;
      const values = watch("firstName");
    
      const onSubmit = (data, e) => {
        console.log("Submit event", e);
        console.log(JSON.stringify(data));
      };
    
      return (
        <form onSubmit={handleSubmit(onSubmit)}>
          <input
            onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
              setValue("firstName", e.target.value);
            }}
          />
          {/*<button>Click</button>*/}
          <div>IsValid: {JSON.stringify(isValid)}</div>
          <div>Errors: {JSON.stringify(errors)}</div>
          <div>Form value: {JSON.stringify(values)}</div>
        </form>
      );
    }
    

    【讨论】:

    • +1 为React.StrictMode,我尝试删除它,它确实删除了额外的渲染。但是,关于我的主要问题,我尝试将name 添加到输入中,但它不起作用。如果是这样,我会觉得很奇怪。我在调用form.setValue() 时已经使用名称'value',为什么在这种情况下需要设置输入name。我可以理解使用带有ref 的表单时需要它。
    • isValid 始终为 false,form.errors 始终为 {},无论输入值是什么。尝试使用您的沙盒。
    • 当然isValid 是假的,你没有提交表格。请检查编辑后的答案,并尝试按提交(enter 键);
    • 查看react-hook-form.com/api/#useForm 的文档,注意我使用的是mode: "onChange"。文档指出:Validation will trigger on the change event with each input, and lead to multiple re-renders. Warning: this often comes with a significant impact on performances.。我不希望仅在提交时进行验证,并且我明确表示使用配置,或者至少这是我理解配置的方式。所以我的问题仍然存在:为什么这不起作用?我错过了什么吗?
    • 是的,你遗漏了一些东西,“关于每个输入的更改事件”,但你没有使用参考,所以为了让它工作,你需要自己调用验证。
    【解决方案2】:

    参考https://github.com/react-hook-form/react-hook-form/issues/2147

    您需要将模式设置为 onChange 或 onBlur

    const { register, handleSubmit, formState: { errors, isDirty, isValid }} = useForm({ mode: 'onChange' });
    

    在这种情况下,“isValid”将按预期工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-28
      • 2019-10-11
      相关资源
      最近更新 更多