useTimeTravelState
Manages state with undo, redo, and navigation across its complete history.
About
useTimeTravelState stores the current value together with past and future values. Use it when undo and redo are not enough and the UI also needs history lengths, multi-step navigation, or a way to replace the current history entry.
Example
import { useTimeTravelState } from "rooks";
export default function HistoryCounter() {
const [value, setValue, controls] = useTimeTravelState(0);
return (
<section>
<p>Value: {value}</p>
<p>
{controls.backLength} past, {controls.forwardLength} future
</p>
<button type="button" onClick={() => setValue((current) => current + 1)}>
Increment
</button>
<button
type="button"
disabled={!controls.canUndo}
onClick={() => controls.undo()}
>
Undo
</button>
<button
type="button"
disabled={!controls.canRedo}
onClick={() => controls.redo()}
>
Redo
</button>
<button type="button" onClick={() => controls.go(-2)}>
Go back two entries
</button>
</section>
);
}Parameters
initialValue: T— required starting value.reset()returns to this value unless a new value is supplied toreset.
The setter accepts either a value or (previousValue: T) => T. Its optional second argument is { overwriteLastEntry?: boolean }; the flag defaults to false.
Return value
The hook returns [value, setValue, controls]:
value: T— the current value.setValue(value, options?)— updates the current value. By default it records the previous value and clears redo history. WithoverwriteLastEntry: true, it keeps the existing past unchanged and still clears redo history.controls.backLengthandcontrols.forwardLength— the number of stored values in each direction.controls.go(step)— moves backward for a negative step and forward for a positive step;0does nothing. Steps beyond the available history stop at the oldest or newest stored value.controls.back(),controls.undo()— move back one entry.controls.forward(),controls.redo()— move forward one entry.controls.reset(newInitialValue?)— clears both history directions and optionally establishes a new reset value.controls.canUndoandcontrols.canRedo— booleans for enabling navigation controls.
Although the current declaration permits an optional argument on back, forward, undo, and redo, those functions move exactly one entry. Use go(step) for multi-step navigation.
Behavior and lifecycle
Updates use React functional state updates, so several setter calls are applied in order. A new value after an undo clears the future branch. The hook creates no subscriptions or external resources, and all history is discarded when the component unmounts.
Changing initialValue after the first render does not reset the state. Call controls.reset(newValue) when that behavior is needed.
Compatibility and accessibility
The hook does not access browser-only APIs and can render during SSR. Disable undo and redo controls using canUndo and canRedo, and give history controls labels that describe their effect.
Related
- useUndoRedoState provides a smaller undo/redo control set with a configurable history limit.
- useUndoState provides one-directional undo history.