Fetching Data
Populate a field from an API on mount with fetch, and refetch when another field changes with fetchDeps.
Some fields need their value from the server - a profile to prefill, a list of options to choose from,
or a value that depends on what the user picked in another field. gform-react handles this with two
props on GInput: fetch and fetchDeps.
fetch?: (input, fields) => void | Partial<FieldState> | Promise<void | Partial<FieldState>>;
fetchDeps?: string[];fetch runs once after the field mounts. Whatever it returns (or its Promise resolves to) is
merged into that field's state - return { value } to populate the field. Add fetchDeps and it
re-runs whenever any listed field's value changes. Both runs are debounced by the field's
debounce (default 300ms), and a pending fetch is cancelled if the
field unmounts.
Fetching on mount
Put fetch on the field you want to populate and return a partial state. It can be async - return a
Promise and gform dispatches the result when it resolves:
import { GForm, GInput } from "gform-react";
async function loadProfile() {
const res = await fetch("/api/me");
return res.json(); // { name: "Ada Lovelace" }
}
export default function ProfileName() {
return (
<GForm onSubmit={(state, e) => { e.preventDefault(); console.log(state.toRawData()); }}>
<GInput
formKey="name"
fetch={async () => {
const profile = await loadProfile();
return { value: profile.name }; // merged into the `name` field
}}
element={(input, props) => <input {...props} />}
/>
<button>Save</button>
</GForm>
);
}The object you return is merged into the field that declares fetch - keyed by its formKey.
Return { value } to set the value; you can also return extra keys (like options or a loading
flag) and read them back from input in element. To seed several fields at once, prefer
GForm's onInit instead.
Try it live
The field shows a loading state, then fills in once the fake request resolves. The loading flag is
just an extra key returned from fetch - it lives on the field state and element reads it from
input.
Refetching on change: fetchDeps
List other fields in fetchDeps and fetch re-runs whenever one of their values changes - the
classic dependent-field pattern (country → cities, zip → city, currency → rate). Read the dependency
from the fields argument:
<GInput
formKey="city"
fetchDeps={["country"]} // re-run fetch when `country` changes
fetch={async (input, fields) => {
const cities = await loadCities(fields.country.value);
return { options: cities, value: cities[0] }; // populate options + pick the first
}}
element={(input, props) => (
<select {...props}>
{(input.options || []).map((c) => <option key={c} value={c}>{c}</option>)}
</select>
)}
/>Because fetch also runs on mount, the dependent field loads its initial options right away - then
again every time the dependency changes.
Dependency changes are detected by value. File values are compared by name, size, type, and last
modified - so a different file re-triggers fetch, but re-selecting the same file does not.
Try it live
Switch the country - the city list reloads (debounced) and resets to the first option each time.
How it works
- When it runs.
fetchfires in the field's mount effect, and again whenever thefetchDepssignature changes. Each run waits out the field'sdebounce(default 300ms), so rapid changes collapse into a single fetch. - What it returns. Return a
Partialfield state (or a Promise of one) and gform merges it into the field byformKey- it doesn't replace the field. Returnundefined/nothing to fetch as a side effect without changing the field (e.g. update other fields via their owndispatchChanges). - Cancellation. If the field unmounts before a debounced fetch fires, gform clears the pending timer - no fetch fires after unmount.
Don't list a field in its own fetchDeps, and be careful chaining fetches that write into each
other's dependencies - each write can re-trigger the next. Keep the dependency direction one-way
(e.g. country → city, never both ways).
See GInput for the prop
reference and Nested Forms for reading other fields with
useFormSelector.