11

这是我的表格和CodeSanbox的样子。目前我正在使用 react-hook-form
,您可以看到表单有 3 个输入。在输入所有必填字段之前,应禁用提交按钮。两个用例:

  1. 如果未选中“检查”:
    • 只有“id”应该被验证并且提交按钮应该被启用。“first”和“last”名称不应成为表单数据的一部分
  2. 如果选中“检查”
    • 所有字段都应验证
      名字,只有在选中“检查”时才需要姓氏。所以它没有被检查然后表单应该只验证“ID”字段。如果选中“检查”,则应验证所有字段。

我遇到的问题是,如果我输入 id,表单状态仍然是“无效的”。表单期望输入名字和姓氏的值。
我将不胜感激任何帮助。

形式

4

4 回答 4

11

我已经更新了您的 CodeSanBox 代码,并在此处添加了完整代码:

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import { useForm } from "react-hook-form";

import "./index.css";

function App() {
  const {
    register,
    handleSubmit,
    errors,
    formState,
    unregister,
    setValue,
    getValues,
    reset
  } = useForm({
    mode: "onBlur",
    reValidateMode: "onBlur",
    shouldUnregister: true
  });
  //console.log(formState.isValid);
  console.log(errors);
  const [disabled, setDisabled] = useState(true);
  const onSubmit = (data) => {
    alert(JSON.stringify(data));
  };
  useEffect(() => {
    // @ts-ignore

    if (disabled) {
      console.log("unregister");
      reset({ ...getValues(), firstName: undefined, lastName: undefined });
      unregister(["firstName", "lastName"]);
    } else {
      console.log("register");
      register("firstName", { required: true });
      register("lastName", { required: true });
    }
  }, [disabled]);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <label htmlFor="id">ID</label>
      <input
        name="id"
        placeholder="id"
        ref={register({ required: true, maxLength: 50 })}
      />
      {errors.id && <p>"ID is required"</p>}
      <fieldset disabled={disabled}>
        <legend>
          <input
            type="checkbox"
            name={"name"}
            ref={register}
            onClick={() => setDisabled(!disabled)}
          />
          <span>Check</span>
        </legend>
        <label htmlFor="firstName">First Name</label>
        <input
          name="firstName"
          placeholder="Bill"
          onChange={(e) => {
            console.log(e.target.value);
            setValue("firstName", e.target.value);
          }}
          ref={register({ required: !disabled })}
        />
        {errors.firstName && <p>"First name is required"</p>}
        <label htmlFor="lastName">Last Name</label>
        <input
          name="lastName"
          placeholder="Luo"
          onChange={(e) => setValue("lastName", e.target.value)}
          ref={register({ required: !disabled })}
        />
        {errors.lastName && <p>"Last name is required"</p>}
      </fieldset>

      <input type="submit" disabled={!formState.isValid} />
    </form>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

首先,我发现您将disabledstate 设置为false应该true作为初始值,关于这个问题,我使用了resetgetValues函数,当disabled状态发生变化时。

为您编辑以轻松识别代码更改,我已在 CodeSanBox 恢复了所有代码。

于 2020-12-15T13:47:57.760 回答
2

整个验证行为 (UX) 肯定会让事情变得更加困难,但是,您应该从库中利用一些东西,例如:

  • watch
  • validate
  • getValues
import React from "react";
import ReactDOM from "react-dom";
import { useForm } from "react-hook-form";

import "./index.css";

function App() {
  const {
    register,
    handleSubmit,
    errors,
    formState: { isValid, touched },
    getValues,
    trigger,
    watch
  } = useForm({
    mode: "onBlur"
  });
  const onSubmit = (data) => {
    alert(JSON.stringify(data));
  };
  const validate = (value) => {
    if (getValues("name")) { // read the checkbox value
      return !!value;
    }

    return true;
  };
  const isChecked = watch("name"); // watch if the name is checked

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <label htmlFor="id">ID</label>
      <input
        name="id"
        placeholder="id"
        ref={register({ required: true, maxLength: 50 })}
      />
      {errors.id && <p>"ID is required"</p>}

      <fieldset disabled={!isChecked}>
        <legend>
          <input
            type="checkbox"
            name={"name"}
            ref={register}
            onChange={() => trigger()} // you want update isValid due to state change, and also those extra two inputs become required
          />
          <span>Check</span>
        </legend>
        <label htmlFor="firstName">First Name</label>
        <input
          name="firstName"
          placeholder="Bill"
          ref={register({
            validate
          })}
        />
        // make sure input is touched before fire an error message to the user
        {errors.firstName && touched["firstName"] && (
          <p>"First name is required"</p>
        )}
        <label htmlFor="lastName">Last Name</label>
        <input
          name="lastName"
          placeholder="Luo"
          ref={register({
            validate
          })}
        />
        {errors.lastName && touched["lastName"] && (
          <p>"Last name is required"</p>
        )}
      </fieldset>

      <input type="submit" disabled={!isValid} />
    </form>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

CSB: https ://codesandbox.io/s/react-hook-form-conditional-fields-forked-n0jig?file=/src/index.js:0-1831

于 2020-12-13T23:10:54.257 回答
0

在你的 ref 上,不要使用硬编码的 bool trueref={register({ required: true})}但是你的动态ref={register({ required: disabled })}

请注意,由于您的配置,在字段模糊mode: "onBlur"之前按钮将无法使用id

于 2020-12-11T20:09:25.697 回答
0

您只需要替换 true .from ref: required:true..... 而是使用 const 'disabled' ....in input of first and last name 。

从而实现动态变化

于 2020-12-11T20:20:56.923 回答