Skip to content

useStateHistory ​

Custom useState that tracks and allows to use previous values.

Demo ​

INFO

The component has:

  • a counter useHistoryState variable with initialState=0 and memory=10.
  • a button to increment counter.
  • a button to increment counter and to disable history.
  • a button to disabled history.
  • a button to enable history.
  • a button to undo operation.
  • a button to redo operation.
  • an input and button to go at specified value.
  • a button to clear history.
Loading demo…
Show source code
tsx
import { useStateHistory } from "../../../..";

function UseStateHistory() {

	const [count, setCount, {go, presentPointer, history, trackUpdate, canRedo, canUndo, redo, undo, clear}] = useStateHistory(0, 10);

	return (<>
		<p>
			Count is {count}
		</p>
		<p>
			Current pointer is {presentPointer}
		</p>
		<p>
			History is {JSON.stringify(history)}
		</p>
		<div style={{ gridTemplateColumns: 'auto auto auto', justifyContent: 'center', display: 'grid', gap: '5px' }}>
			<button onClick={() => setCount((count) => (count + 1))}>
				increment
			</button>
			<button onClick={() => setCount((count) => {
				trackUpdate(false);
				return count + 1;
			})}>
				disableHistory and increment
			</button>
			<button onClick={() => trackUpdate(false)}>
				disable history
			</button>
			<button onClick={() => trackUpdate(true)}>
				enable history
			</button>
			<button onClick={() => clear()}>Clear</button>
			<button onClick={undo} disabled={!canUndo}>Undo</button>
			<button onClick={redo} disabled={!canRedo}>Redo</button>
			<button onClick={() => go(+(document.querySelector('#go') as HTMLInputElement).value)}>
				Go
				<input type='number' id='go' style={{ marginLeft: 35, maxWidth: 40 }} />
			</button>
		</div>
	</>);
}

UseStateHistory.displayName = "UseStateHistory";

export { UseStateHistory };

Types ​

StateHistoryControls ​

  • @template T - The type of the state value.

The history controls object returned as part of {@link UseStateHistoryResult} and {@link UseStateHistoryGetterResult}.

PropertyTypeRequiredDescription
historyreadonly T[]✓A read-only array of all recorded state snapshots, from oldest to most recent. The entry at presentPointer is the currently active state.
presentPointernumber✓The index within history that corresponds to the current state. Moves backward on undo and forward on redo or a new state update.
trackUpdate(enable: boolean) => void✓Enables or disables history recording. When called with false, state updates still trigger re-renders but are not added to history. Re-enable with true to resume recording.
canUndoboolean✓true when there is at least one state snapshot before presentPointer that can be restored via undo.
canRedoboolean✓true when there is at least one state snapshot after presentPointer that can be restored via redo.
undo() => void✓Moves presentPointer one step backward in history and restores the corresponding state. No-op when canUndo is false.
redo() => void✓Moves presentPointer one step forward in history and restores the corresponding state. No-op when canRedo is false.
go(index: number) => void✓Jumps directly to the state at the given index in history, updating presentPointer and restoring that snapshot.
clear(value?: T) => void✓Clears the entire history array. When value is provided, the cleared history is replaced with a single entry equal to value; otherwise the history is reset to the current state only.

UseStateHistoryProps ​

  • @template T - The type of the state value.

Parameters accepted by useStateHistory and useStateHistoryGetter.

PropertyTypeRequiredDescription
initialStateT \| (() => T)✓The initial state value. Accepts either a direct value or a lazy initializer function invoked only on the first render.
capacitynumber \| "no-limit"Maximum number of state snapshots retained in history: - "no-limit" (default) — All snapshots are retained indefinitely. - number — Once the limit is reached, the oldest snapshot is evicted to make room for the new one (FIFO).

UseStateHistoryResult ​

  • @template T - The type of the state value.

Return value of useStateHistory.

IndexTypeDescription
[0]TThe current state value, reactive — triggers a re-render when updated.
[1]Dispatch<SetStateAction<T>>A stable setter (same semantics as the setter returned by useState). Accepts either a new value or an updater function receiving the current state and returning the next.
[2]StateHistoryControls<T>The history controls object. See {@link StateHistoryControls}.

UseStateHistoryGetterResult ​

  • @template T - The type of the state value.

Return value of useStateHistoryGetter.

IndexTypeDescription
[0]TThe current state value, reactive — triggers a re-render when updated.
[1]Dispatch<SetStateAction<T>>A stable setter (same semantics as the setter returned by useState). Accepts either a new value or an updater function receiving the current state and returning the next.
[2]() => TA stable getter that returns the current state value synchronously without causing a re-render. Useful for reading state inside callbacks without adding it as a dependency.
[3]StateHistoryControls<T>The history controls object. See {@link StateHistoryControls}.

Released under the MIT License.