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
@templateT - The type of the state value.
The history controls object returned as part of {@link UseStateHistoryResult} and {@link UseStateHistoryGetterResult}.
| Property | Type | Required | Description |
|---|---|---|---|
history | readonly T[] | ✓ | A read-only array of all recorded state snapshots, from oldest to most recent. The entry at presentPointer is the currently active state. |
presentPointer | number | ✓ | 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. |
canUndo | boolean | ✓ | true when there is at least one state snapshot before presentPointer that can be restored via undo. |
canRedo | boolean | ✓ | 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
@templateT - The type of the state value.
Parameters accepted by useStateHistory and useStateHistoryGetter.
| Property | Type | Required | Description |
|---|---|---|---|
initialState | T \| (() => T) | ✓ | The initial state value. Accepts either a direct value or a lazy initializer function invoked only on the first render. |
capacity | number \| "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
@templateT - The type of the state value.
Return value of useStateHistory.
| Index | Type | Description |
|---|---|---|
[0] | T | The 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
@templateT - The type of the state value.
Return value of useStateHistoryGetter.
| Index | Type | Description |
|---|---|---|
[0] | T | The 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] | () => T | A 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}. |
