Dispatching Changes
Programmatically update fields - set values, surface errors, or attach your own custom data to form state, at the field or form level.
Most of the time gform-react updates itself as the user types. But sometimes you need to write into
the form: prefill values, surface an error from the server, or stash some custom data on a field. That's
what dispatchChanges is for. It comes in two flavors - one on a single field, one on the whole
form - and both merge into state rather than replacing it.
Field level: state.<formKey>.dispatchChanges
Every field exposes dispatchChanges(changes, options?). Pass a partial field state and gform merges
it into that field:
state.email.dispatchChanges({ value: "ada@example.com" });By default this does not re-run validation - which is exactly what you want when you're surfacing an error yourself (e.g. one the server returned):
// a manually-set error sticks; gform won't validate it away
state.email.dispatchChanges({ error: true, errorText: "Already registered" });Pass { validate: true } to re-run the field's validators against the new value - use this when a
programmatic value change should also update validity:
// set the value AND re-check rules; a `required` field cleared this way will now show its error
state.email.dispatchChanges({ value: "" }, { validate: true });Without { validate: true }, dispatchChanges only merges - it won't touch error/errorText.
That's deliberate: it lets you set a manual error (or any state) without gform immediately
re-validating it away. Add the option when you want the change reflected in form validity.
Form level: state.dispatchChanges
The form state has its own dispatchChanges that updates any number of fields in one call -
keyed by formKey. Handy for seeding several fields at once:
state.dispatchChanges({
firstName: { value: "Ada" },
lastName: { value: "Lovelace" },
});Each field object is merged (not replaced), so the rest of that field's state is preserved. The
form-level call doesn't take the { validate: true } option - if you need validation, call the
field's own dispatchChanges with it.
Attaching custom data
A field's state isn't limited to the built-in keys. Any extra keys you dispatch are merged onto the field and kept there - gform doesn't strip them. This makes form state a convenient home for transient, field-scoped data:
state.avatar.dispatchChanges({ uploading: true });
state.country.dispatchChanges({ options: ["France", "Japan", "Brazil"] });
state.email.dispatchChanges({ meta: { checkedAt: Date.now() } });Custom keys show up everywhere the field state is read:
- inside that field's
elementrender prop -input.uploading,input.options - via
useFormSelector-useFormSelector((s) => s.fields.avatar.uploading) - in a
fetchcallback -fetch(input, fields)seesfields.country.options
toRawData(), toFormData(), and toURLSearchParams() only read each field's value - they
ignore custom keys. Use custom data for UI/transient state (loading flags, fetched option lists,
metadata); use value for anything you want in the submitted payload. See
Reading Form State.
Updating from a child component
dispatchChanges doesn't require the render prop. Any component inside the form can grab a field with
useFormSelector and call its dispatchChanges - no prop drilling:
import { useFormSelector } from "gform-react";
function ClearEmailButton() {
const email = useFormSelector((state) => state.fields.email);
return (
<button type="button" onClick={() => email.dispatchChanges({ value: "" }, { validate: true })}>
Clear email
</button>
);
}See Nested Forms for more on reaching form state from deep in the tree.
Try it live
Autofill fills both fields in one form-level call. Tag attaches a custom badge key that the
render prop shows next to the label (and the <pre> echoes it) - yet it never appears in the submitted
data. Clear + validate empties last name and re-runs its rule, so the Required error surfaces.
See Core Concepts for the full state reference and
Constraint Validation for how rules run.