gform-react
Back to Guides

Conditional Fields

Show, hide, or require fields based on another field's value - and keep form validity correct as they appear and disappear.

Forms often change shape based on what the user picks: a "Business" account reveals a company name, a "Other" option reveals a free-text box. With gform-react you do this with plain React - read a field's value and conditionally render the dependent GInputs.

The important part is what happens to validity: a GInput registers when it mounts and unregisters when it unmounts. So a hidden field's value leaves form state and stops counting toward isValid/isInvalid - a conditionally-hidden required field won't block submit while it's not showing. (Same lifecycle that powers Dynamic Fields.)

Reading a value to decide what renders

Take the function child to access state, read the controlling field's value, and branch:

AccountForm.tsx
<GForm<AccountForm> validators={validators} onSubmit={handleSubmit}>
  {(state) => (
    <>
      <GInput
        formKey="accountType"
        value="personal"
        element={(input, props) => (
          <select {...props}>
            <option value="personal">Personal</option>
            <option value="business">Business</option>
          </select>
        )}
      />
 
      {/* Only mounted - and only required - when "business" is selected */}
      {state.accountType?.value === "business" && (
        <GInput
          formKey="companyName"
          required
          element={(input, props) => (
            <label>
              <span>Company name</span>
              <input {...props} />
              {input.error && <small>{input.errorText}</small>}
            </label>
          )}
        />
      )}
 
      <button disabled={state.isInvalid}>Continue</button>
    </>
  )}
</GForm>

When the user switches back to "Personal", companyName unmounts: its value drops out of toRawData() and the form is valid again without it.

Unmounting clears the field's value

Because hidden fields unregister, toggling one off and on again starts it fresh (re-seeded from its value prop, if any). That's usually what you want for conditional fields. If you need to keep a hidden field's value, render it always and hide it with CSS (hidden / display: none) instead of unmounting it - it stays registered and keeps contributing to validity.

Reading from a deep child with useFormSelector

If the controlling field and the conditional field live in different components, you don't need the render prop - subscribe to just the value you care about with useFormSelector:

import { useFormSelector } from "gform-react";
 
function CompanyFields() {
  const accountType = useFormSelector((state) => state.fields.accountType?.value);
  if (accountType !== "business") return null;
  return <GInput formKey="companyName" required element={/* … */} />;
}

It re-renders only when accountType changes, so the rest of the form stays untouched. See Nested Forms for more.

Try it live

Loading playground…

Switch to Business and the company fields appear (and companyName becomes required); tick the newsletter box and a frequency field appears. The toRawData() readout shows only the fields that are currently mounted.

See Dynamic Fields for adding/removing repeated fields and Dispatching Changes for setting values programmatically.