Search code examples
reactjsreact-hooksreact-hook-formreact-forms

Conditional validation with react hook form


Here is my form looks like and also CodeSanbox. currently I'm using react-hook-form
as you can see form has 3 inputs. Submit button should be disabled until all the required fields are entered. Two use case:

  1. If "Check" is unchecked:
    • only "id" should be validated and submit button should get enabled. "firt" and "last" names should not be part of form data
  2. If "Check" is checked
    • all the fields should be validated
      first and last names are only required if "Check" is checked. so its not checked then form should only validate "ID" field. if "Check" is checked then all fields should get validated.

problem I'm having is if I enter id, form state is still "invalid". Form is expecting to enter values for first and last name.
I would appreciate any help.

Form


Solution

  • I have updated your CodeSanBox code and also adding the full code here:

    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);
    
    

    First I found that you set disabled state as false which should be true as an initial value, and regarding the issue, I have used reset and getValues functions when the disabled state changes.

    EDIT for you to recognize code changes easy, I have restored all the code at CodeSanBox.