History workflow
This example adds managed value history to a generated profile form while React Hook Form continues to own live values, validation, dirty state, and arrays.
Try the workflow
- Change Name several times.
- Add or edit a project.
- Select Undo, then Redo.
- Select Export, make another change, then select Import.
- Select Clear history to retain only the current position.
Managed value history
Edit the name or projects, then navigate the retained input positions.
The position output follows retained groups. Operations leave the live form active when no target is available or middleware cancels a restore.
What this example shows
createHistoryMiddlewareas an optionalform-please/historyfeature.useHistory(form, feature)for the exact configured form.- The hook's reactive
snapshotfor navigation state. - Managed restore through hooks and ordered middleware.
- Full input snapshots in
HistoryJournalversion 1.
Copy the source
"use client"
import {
,
type ,
type ,
type ,
,
} from "form-please/history"
import { } from "form-please/preset-native"
import { } from "react"
import { } from "zod"
const = .({
: .().(1, "Enter a name"),
: .(.({ : .() })),
})
type = .<typeof >
const = .(, {
: [
{ : "text", : "field", : "Name", : "name" },
{
: [
{
: "text",
: "field",
: "Project title",
: "title",
},
],
: { : "" },
: "array",
: "Projects",
: "projects",
},
],
})
const = ({ : 50 })
export function () {
const = .(, {
: { : "Ada Lovelace", : [] },
: [],
})
const = (, )
const { } =
const [, ] = <<>>()
const [, ] = ("Edit the form to create history.")
async function (
: string,
: <>,
) {
try {
(`${}: ${await }`)
} catch () {
if ( instanceof ) {
(.)
} else {
(`${} failed`)
}
}
}
return (
<
="Managed value history preview"
="form-please-complex form-please-lab"
>
< ="form-please-lab__kicker">Managed value history</>
< ="form-please-lab__summary">
Edit the name or projects, then navigate the retained input positions.
</>
<. ="form-please-lab__form" ={}>
< ="form-please-lab__actions">
<
={!.}
={() => void ("Undo", .())}
="button"
>
Undo
</>
<
={!.}
={() => void ("Redo", .())}
="button"
>
Redo
</>
<
={. === 0}
={() => void ("Seek", .(0))}
="button"
>
First position
</>
<
={() => {
const = .()
()
(`Exported ${..} positions.`)
}}
="button"
>
Export
</>
<
={ === }
={() => {
if ( !== ) {
void ("Import", .())
}
}}
="button"
>
Import
</>
<
={() => {
.()
("History cleared at the current values.")
}}
="button"
>
Clear history
</>
</>
< ="polite">
{} Position {.} of {.}.
</>
</.>
</>
)
}
export async function (
: <>,
: <>,
): <> {
const = .()
return .()
}Read Managed value history for grouping, retention, raw RHF boundaries, operation results, and journal limits.