React Hook Form 10 ๐ Setting and Resetting Values โ setValue, reset, and defaultValues
The setValue, the reset, and the defaultValues are the three APIs that control the form’s values from outside the input elements. The defaultValues is the initial state and the comparison baseline. The setValue is the programmatic update for a single field. The reset is the programmatic update for the whole form. The three are related but distinct, and the distinction matters because the dirty tracking, the touched tracking, and the validation all depend on which one is used and how.
The defaultValues is read once when the form mounts, and it is the reference point for the isDirty comparison. The setValue writes to the internal form state and marks the field as dirty (by default), and it can trigger the validation. The reset restores the form to the defaultValues or to the new values passed to it, and it clears the dirty, the touched, and the error state unless the keepDirty, the keepTouched, or the keepErrors options are set. The three are the value lifecycle, and the correct combination is the form’s behavior.
Key point: The defaultValues is the initial state and the dirty baseline, read once at mount. The setValue writes a single field and marks it dirty unless shouldDirty: false. The reset restores the whole form and clears the errors, the dirty, and the touched state unless the keep* options are set. The reset with the new values is the mechanism for the async data load, and the defaultValues with the values prop is the alternative for the reactive data.
Why the three APIs exist
The initial-state problem. The form needs an initial state before the user interacts with it, and the defaultValues is that state. The library reads the defaultValues once at mount, and it uses the value as the baseline for the isDirty comparison. A missing field in the defaults makes the comparison unreliable, because the library has no reference point for the field . The defaultValues is the mechanism that makes the dirty tracking and the reset work.
The programmatic-update problem. A form that loads the data from the API needs to set the values after the fetch. The setValue is the mechanism for a single field, and the reset is the mechanism for the whole form. The setValue writes to the internal state and triggers the validation and the dirty tracking, and the reset replaces the whole state and clears the interaction history . The two are the different granularities of the same update.
The async-data problem. The data arrives after the form has mounted, and the defaultValues is read once. The values prop is the reactive alternative: the library watches the prop and resets the form when the prop changes . The reset in the useEffect is the imperative alternative, and the two are the different patterns for the same requirement.
The reset-options problem. The reset clears the dirty, the touched, and the error state by default. A form that wants to keep the interaction history across the reset uses the keepDirty, the keepTouched, and the keepErrors options. The keepValues option is the mechanism that keeps the current values while resetting the errors . The options are the mechanism that makes the reset flexible.
The setValue-options problem. The setValue marks the field as dirty by default, and it does not trigger the validation unless the shouldValidate option is set. The shouldTouch option is the mechanism that marks the field as touched, and the shouldDirty option is the mechanism that controls the dirty tracking . The options are the mechanism that lets the programmatic update mimic the user input or stay silent.
a. The defaultValues and the setValue function
The defaultValues is the initial state. It can be an object, a function that returns the object, or a promise that resolves to the object . The function form is the mechanism for the expensive computation, and the promise form is the mechanism for the async data.
// The defaultValues forms
import { useForm } from "react-hook-form";
type ProfileFormValues = {
name: string;
email: string;
};
function ProfileForm() {
// The object form.
const form = useForm<ProfileFormValues>({
defaultValues: { name: "", email: "" },
});
// The function form.
const formWithFunction = useForm<ProfileFormValues>({
defaultValues: () => ({ name: "", email: "" }),
});
// The promise form.
const formWithPromise = useForm<ProfileFormValues>({
defaultValues: fetchProfile(),
});
return <form />;
}
The object form is the simplest, and the function form is the mechanism for the expensive computation that should not run on every render. The promise form is the mechanism for the async data, and the form waits for the promise to resolve before the first render . The defaultValues is cached after the first read, and the change to the prop after the mount does not update the form unless the values prop is used.
The setValue function writes a single field. The signature is setValue(name, value, options), and the options are the shouldValidate, the shouldDirty, and the shouldTouch .
// The setValue with the options
function ProfileForm() {
const { register, setValue } = useForm<ProfileFormValues>({
defaultValues: { name: "", email: "" },
});
const handleLoad = () => {
// The setValue writes the name field.
// The shouldValidate triggers the validation.
// The shouldDirty marks the field as dirty.
// The shouldTouch marks the field as touched.
setValue("name", "Ada", {
shouldValidate: true,
shouldDirty: true,
shouldTouch: true,
});
};
return (
<form>
<input {...register("name")} />
<button type="button" onClick={handleLoad}>Load</button>
</form>
);
}
The shouldValidate: true is the mechanism that runs the validation for the field after the set, and the error is stored in the formState.errors if the value is invalid. The shouldDirty: true is the mechanism that marks the field as dirty, and the isDirty becomes true. The shouldTouch: true is the mechanism that marks the field as touched, and the touchedFields updates. The three options are the mechanism that makes the programmatic update mimic the user input.
The setValue on a nested field uses the dot syntax, and the setValue("address.city", "London") writes the nested value . The setValue on the array field uses the index path, and the setValue("items.0.name", "Book") writes the first item’s name. The nested and the array paths are the same mechanism as the register naming.
b. The reset function and the reset options
The reset function restores the form to the defaultValues or to the new values. The signature is reset(values, options), and the options are the keepErrors, the keepDirty, the keepValues, the keepDefaultValues, the keepIsSubmitted, the keepTouched, the keepIsValid, and the keepSubmitCount .
// The reset with the new values
function ProfileForm() {
const { register, reset } = useForm<ProfileFormValues>({
defaultValues: { name: "", email: "" },
});
const handleReset = () => {
// The reset restores the default values.
reset();
};
const handleResetToNew = () => {
// The reset sets the new values as the new defaults.
reset({ name: "Ada", email: "ada@example.com" });
};
return (
<form>
<input {...register("name")} />
<input {...register("email")} />
<button type="button" onClick={handleReset}>Reset</button>
<button type="button" onClick={handleResetToNew}>Reset to Ada</button>
</form>
);
}
The reset() with no arguments restores the original defaultValues. The reset(newValues) sets the new values as the new defaults, and the isDirty compares the current values against the new defaults . The difference matters for the dirty tracking: the reset(newValues) clears the dirty state because the new values are the new baseline.
The keepValues option is the mechanism that keeps the current values while resetting the errors. The keepDirty is the mechanism that keeps the dirty state, and the keepTouched is the mechanism that keeps the touched state.
// The reset with the keep options
function ProfileForm() {
const { register, reset } = useForm<ProfileFormValues>({
defaultValues: { name: "", email: "" },
});
const handleClearErrors = () => {
// The keepValues keeps the current values.
// The keepDirty keeps the dirty state.
// The keepTouched keeps the touched state.
reset(undefined, {
keepValues: true,
keepDirty: true,
keepTouched: true,
});
};
return (
<form>
<input {...register("name")} />
<button type="button" onClick={handleClearErrors}>Clear errors</button>
</form>
);
}
The keepValues: true is the mechanism that clears the errors without resetting the values. The keepDirty: true and the keepTouched: true are the mechanisms that keep the interaction history. The three options are the mechanism that lets the reset do the partial restore, and the partial restore is the reason the reset is not a single operation.
The values prop is the reactive alternative to the reset in the useEffect. The prop is watched, and the form resets when the prop changes . The reset in the useEffect is the imperative alternative, and the two are the different patterns for the same requirement.
// The values prop
function ProfileForm({ user }: { user: ProfileFormValues }) {
const { register } = useForm<ProfileFormValues>({
// The values prop updates the form when the user changes.
values: user,
});
return <form><input {...register("name")} /></form>;
}
The values prop is the mechanism that makes the form reactive to the external data. The reset in the useEffect is the mechanism that gives the explicit control. The two are the alternatives, and the choice is the control against the simplicity.
Complete Example Session
// ============================================
// PART 1: THE DEFAULT VALUES
// ============================================
import { useForm } from "react-hook-form";
type ProfileFormValues = {
name: string;
email: string;
};
function ProfileForm() {
const { register } = useForm<ProfileFormValues>({
// The defaultValues is the initial state and the dirty baseline.
defaultValues: { name: "", email: "" },
});
return (
<form>
<input {...register("name")} />
<input {...register("email")} />
</form>
);
}
// ============================================
// PART 2: THE DEFAULT VALUES FUNCTION
// ============================================
function ProfileForm() {
const { register } = useForm<ProfileFormValues>({
// The function form is for the expensive computation.
defaultValues: () => ({ name: "", email: "" }),
});
return <form><input {...register("name")} /></form>;
}
// ============================================
// PART 3: THE SETVALUE
// ============================================
function ProfileForm() {
const { register, setValue } = useForm<ProfileFormValues>({
defaultValues: { name: "", email: "" },
});
const handleLoad = () => {
// The setValue writes the field.
setValue("name", "Ada", { shouldValidate: true, shouldDirty: true });
};
return (
<form>
<input {...register("name")} />
<button type="button" onClick={handleLoad}>Load</button>
</form>
);
}
// ============================================
// PART 4: THE NESTED SETVALUE
// ============================================
setValue("address.city", "London");
setValue("items.0.name", "Book");
// The dot syntax is the nested path.
// ============================================
// PART 5: THE RESET
// ============================================
function ProfileForm() {
const { register, reset } = useForm<ProfileFormValues>({
defaultValues: { name: "", email: "" },
});
const handleReset = () => {
// The reset restores the default values.
reset();
};
const handleResetToNew = () => {
// The reset sets the new values as the new defaults.
reset({ name: "Ada", email: "ada@example.com" });
};
return (
<form>
<input {...register("name")} />
<button type="button" onClick={handleReset}>Reset</button>
<button type="button" onClick={handleResetToNew}>Reset to Ada</button>
</form>
);
}
// ============================================
// PART 6: THE KEEP OPTIONS
// ============================================
function ProfileForm() {
const { register, reset } = useForm<ProfileFormValues>({
defaultValues: { name: "", email: "" },
});
const handleClearErrors = () => {
// The keepValues keeps the current values.
reset(undefined, {
keepValues: true,
keepDirty: true,
keepTouched: true,
});
};
return (
<form>
<input {...register("name")} />
<button type="button" onClick={handleClearErrors}>Clear errors</button>
</form>
);
}
// ============================================
// PART 7: THE VALUES PROP
// ============================================
function ProfileForm({ user }: { user: ProfileFormValues }) {
const { register } = useForm<ProfileFormValues>({
// The values prop updates the form when the user changes.
values: user,
});
return <form><input {...register("name")} /></form>;
}
// ============================================
// PART 8: THE RESET AFTER THE SUBMIT
// ============================================
const onSubmit = async (data: ProfileFormValues) => {
await fetch("/api/profile", { method: "POST", body: JSON.stringify(data) });
// The reset clears the form after the successful submission.
reset();
};
// ============================================
// PART 9: THE RESET WITH THE ASYNC DATA
// ============================================
function ProfileForm({ userId }: { userId: string }) {
const { register, reset } = useForm<ProfileFormValues>({
defaultValues: { name: "", email: "" },
});
useEffect(() => {
// The fetch resolves after the mount.
fetch(`/api/users/${userId}`)
.then((response) => response.json())
.then((user) => reset(user));
}, [userId, reset]);
return <form><input {...register("name")} /></form>;
}
// ============================================
// PART 10: THE CHECKLIST
// ============================================
// [ ] The defaultValues is set for every field.
// [ ] The setValue has the shouldValidate and the shouldDirty options.
// [ ] The reset clears the dirty and the touched state.
// [ ] The keepValues is used for the error clearing.
// [ ] The values prop is used for the reactive data.
// [ ] The reset in the useEffect is used for the imperative data.
The ten parts covered the defaultValues, the defaultValues function, the setValue, the nested setValue, the reset, the keep options, the values prop, the reset after the submit, the reset with the async data, and the checklist. The through-line is that the three APIs control the values, and the options control the tracking.
Quick Reference
The defaultValues forms
| Form | Purpose |
|---|---|
| The object | The static initial state |
| The function | The expensive computation |
| The promise | The async data |
The setValue options
| Option | Effect |
|---|---|
shouldValidate | Run the validation after the set |
shouldDirty | Mark the field as dirty |
shouldTouch | Mark the field as touched |
The reset options
| Option | Preserves |
|---|---|
keepValues | The current values |
keepDirty | The dirty state |
keepTouched | The touched state |
keepErrors | The errors |
keepDefaultValues | The original defaults |
keepIsSubmitted | The submitted state |
keepSubmitCount | The submit count |
The values prop vs the reset
| Aspect | values prop | reset in the effect |
|---|---|---|
| The reactive | Yes | No |
| The explicit control | No | Yes |
| The dirty tracking | Compares against the prop | Compares against the new defaults |
Best Practices
โ Do This:
// Provide the defaultValues for every field
useForm({ defaultValues: { name: "", email: "" } }); // โ
// Use the shouldValidate for the programmatic set
setValue("name", "Ada", { shouldValidate: true }); // โ
// Use the keepValues for the error clearing
reset(undefined, { keepValues: true }); // โ
// Use the values prop for the reactive data
useForm({ values: user }); // โ
โ Don’t Do This:
// Omit the defaultValues
useForm(); // the isDirty is unreliable // โ
// Use the reset without the keepValues to clear the errors
reset(); // the values are also reset // โ
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
The isDirty is always true | The defaultValues is missing | Set the defaultValues |
The setValue does not show the validation error | The shouldValidate is not set | Add the option |
The reset clears the values unexpectedly | The keepValues is not set | Add the option |
| The async data does not populate the form | The reset is not called after the fetch | Call the reset(user) |
Real-World Examples
1. The defaultValues
useForm({ defaultValues: { name: "", email: "" } })
2. The defaultValues function
useForm({ defaultValues: () => ({ name: "", email: "" }) })
3. The setValue
setValue("name", "Ada")
4. The setValue with the options
setValue("name", "Ada", { shouldValidate: true, shouldDirty: true })
5. The nested setValue
setValue("address.city", "London")
6. The reset
reset()
7. The reset to new values
reset({ name: "Ada", email: "ada@example.com" })
8. The keepValues
reset(undefined, { keepValues: true })
9. The values prop
useForm({ values: user })
10. The reset with the async data
reset(user)
Visual
The Three APIs
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ THE VALUE LIFECYCLE โ
โ โ
โ The mount โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ defaultValues โ The initial state and the baselineโ
โ โโโโโโโโโโโโฌโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ setValue โ The single field update โ
โ โโโโโโโโโโโโฌโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ reset โ The whole form restore โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The Reset Options
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ THE RESET OPTIONS โ
โ โ
โ reset() โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ The values are resetโ The errors are cleared โ
โ โ The dirty is clearedโ The touched is cleared โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ reset(undefined, { keepValues: true }) โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ The values are kept โ The errors are cleared โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The Async Data
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ THE ASYNC DATA โ
โ โ
โ The form mounts with the defaultValues โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ The fetch resolves โ The data arrives โ
โ โโโโโโโโโโโโฌโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ reset(user) โ The form is populated โ
โ โ โ The new values are the defaults โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Item | Value |
|---|---|
defaultValues | The initial state and the dirty baseline |
setValue | The single field update, with the options |
reset | The whole form restore, with the keep options |
The setValue options | shouldValidate, shouldDirty, shouldTouch |
The reset options | keepValues, keepDirty, keepTouched, keepErrors |
The values prop | The reactive alternative to the reset |
Key takeaways:
- The
defaultValuesis the initial state and the dirty baseline. It is read once at mount, and theisDirtycompares the current values against it. A missing field makes the comparison unreliable . - The
setValuewrites a single field and marks it dirty by default. TheshouldValidateoption runs the validation, and theshouldDirtyand theshouldTouchoptions control the tracking. The dot syntax is the nested path . - The
resetrestores the whole form and clears the interaction state. Thereset()restores the original defaults, and thereset(newValues)sets the new values as the new defaults. The keep options preserve the specific parts . - The
keepValuesis the error-clearing mechanism. Thereset(undefined, { keepValues: true })clears the errors without resetting the values, and thekeepDirtyand thekeepTouchedpreserve the interaction history . - The
valuesprop is the reactive alternative to the reset. The prop is watched, and the form resets when the prop changes. Theresetin theuseEffectis the imperative alternative .
Remember: The React Hook Form has three APIs for the values. The defaultValues is the initial state and the baseline, the setValue is the single field update, and the reset is the whole form restore. The options control the tracking and the preservation. The values prop is the reactive alternative, and the reset in the effect is the imperative one. The three are the lifecycle, and the options are the control.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!