Edit existing data
A form that edits a saved record renders with the current values already in place. This page covers handing it those values, knowing whether anything changed with isDirty, and putting things back.
On this page
Fill the fields with the current values
Hand the current values over as defaultValue, or defaultChecked for a checkbox. The DOM keeps the values, so there is no need to control them with value.
edit-talk-form.tsxconst title = form.field('title');
const isPublic = form.field('public');
<input defaultValue={talk.title} {...title.input} />
<input defaultChecked={talk.public} {...isPublic.input} />Write defaultValue before spreading input. After a failed submission, input carries the submitted value as defaultValue. Spread after yours, it overrides it, so the field shows what was sent after a failure and the current value otherwise.
Pitfall
Write defaultValue after the spread, and it overrides the submitted value too: a failed submission wipes out what the person typed.
Know whether anything changed
form.isDirty is true once any field differs from the value it was rendered with. Adding or removing a row counts as a change too.
It compares each control with its defaultValue, read straight from the DOM, so typing never re-renders: only a flip of isDirty does.
For example, ask before the person leaves the page with unsaved changes.
edit-talk-form.tsxuseEffect(() => {
if (!form.isDirty) return;
const confirm = (event: BeforeUnloadEvent) => {
event.preventDefault();
};
addEventListener('beforeunload', confirm);
return () => {
removeEventListener('beforeunload', confirm);
};
}, [form.isDirty]);Pitfall
Avoid disabling the submit button with disabled={!form.isDirty}. In the server-rendered HTML isDirty is still false, so the button cannot be pressed until JavaScript arrives. After a failed submission the submitted values become the new defaults too, so sending again unchanged is no longer possible.
Put things back
A type="reset" button makes the browser put every field back to its defaultValue. useForm notices the reset, clears the errors it was showing, and takes isDirty back to false.
<button type="reset">Revert</button>React resets the form the same way after a Server Action. A failed submission keeps what was typed because the submitted values render as defaultValue, and the reset goes back to them.
Try the dirty state
A form that edits a saved talk, with the current values handed over as defaultValue.
Try it
- Edit the title. The badge changes to “Changed”.
- Type the original title back. The badge returns to “No changes”.
- Uncheck “Public”, then press “Revert”. Both the values and the badge go back.