Skip to content

useManualHistory

A hook for manually managing Observable change history. It only records a snapshot when commit() is called, and allows navigating previous states via undo/redo. Useful when auto-tracking is not needed, or when you want to record history only on explicit “save” actions.

Manual Save Points
Draft freely, commit intentionally

The counter can move as much as you want, but history updates only when you explicitly save a snapshot.

Counter draft

Increment or decrement first, then decide when that state deserves a place in history.

Saved
0
Saved timeline

Newest snapshot is pinned at the top.

#1
0
import {
function useObservable<T>(): Observable<T | undefined> (+3 overloads)

A React hook that creates a new observable

@paraminitialValue The initial value of the observable or a function that returns the initial value

@seehttps://www.legendapp.com/dev/state/react/#useObservable

useObservable
} from "@legendapp/state/react";
import {
import useManualHistory
useManualHistory
} from "@usels/web";
const
const counter$: any
counter$
=
useObservable<unknown>(value: Promise<unknown> | (() => unknown) | unknown, deps?: React.DependencyList): any (+3 overloads)

A React hook that creates a new observable

@paraminitialValue The initial value of the observable or a function that returns the initial value

@seehttps://www.legendapp.com/dev/state/react/#useObservable

useObservable
(0);
const {
const commit: any
commit
,
const undo: any
undo
,
const redo: any
redo
,
const canUndo$: any
canUndo$
,
const canRedo$: any
canRedo$
} =
import useManualHistory
useManualHistory
(
const counter$: any
counter$
);
const counter$: any
counter$
.
any
set
(1);
const commit: any
commit
(); // snapshot: 1
const counter$: any
counter$
.
any
set
(2);
const commit: any
commit
(); // snapshot: 2
const undo: any
undo
(); // counter$ → 1
const redo: any
redo
(); // counter$ → 2
import {
function useObservable<T>(): Observable<T | undefined> (+3 overloads)

A React hook that creates a new observable

@paraminitialValue The initial value of the observable or a function that returns the initial value

@seehttps://www.legendapp.com/dev/state/react/#useObservable

useObservable
} from "@legendapp/state/react";
import {
import useManualHistory
useManualHistory
} from "@usels/web";
const
const value$: any
value$
=
useObservable<unknown>(value: Promise<unknown> | (() => unknown) | unknown, deps?: React.DependencyList): any (+3 overloads)

A React hook that creates a new observable

@paraminitialValue The initial value of the observable or a function that returns the initial value

@seehttps://www.legendapp.com/dev/state/react/#useObservable

useObservable
(0);
// Keep at most 10 undo steps; older records are discarded automatically
const {
const commit: any
commit
,
const undo: any
undo
} =
import useManualHistory
useManualHistory
(
const value$: any
value$
, {
capacity: number
capacity
: 10 });

Use dump and parse to store a compact or transformed representation instead of raw value clones.

import {
function useObservable<T>(): Observable<T | undefined> (+3 overloads)

A React hook that creates a new observable

@paraminitialValue The initial value of the observable or a function that returns the initial value

@seehttps://www.legendapp.com/dev/state/react/#useObservable

useObservable
} from "@legendapp/state/react";
import {
import useManualHistory
useManualHistory
} from "@usels/web";
const
const items$: any
items$
=
useObservable<{}>(value: Promise<{}> | (() => {}) | {}, deps?: React.DependencyList): any (+3 overloads)

A React hook that creates a new observable

@paraminitialValue The initial value of the observable or a function that returns the initial value

@seehttps://www.legendapp.com/dev/state/react/#useObservable

useObservable
<string[]>([]);
const {
const commit: any
commit
,
const undo: any
undo
,
const history$: any
history$
} =
import useManualHistory
useManualHistory
(
const items$: any
items$
, {
// Store as comma-separated string to save memory
dump: (arr: any) => any
dump
: (
arr: any
arr
) =>
arr: any
arr
.
any
join
(","),
parse: (str: any) => any
parse
: (
str: any
str
) => (
str: any
str
?
str: any
str
.
any
split
(",") : []),
});
const items$: any
items$
.
any
set
(["a", "b", "c"]);
const commit: any
commit
(); // stored as "a,b,c"
const undo: any
undo
(); // restored to ["a", "b", "c"]

reset() restores the source to the last committed value without touching the undo/redo stacks.

import {
function useObservable<T>(): Observable<T | undefined> (+3 overloads)

A React hook that creates a new observable

@paraminitialValue The initial value of the observable or a function that returns the initial value

@seehttps://www.legendapp.com/dev/state/react/#useObservable

useObservable
} from "@legendapp/state/react";
import {
import useManualHistory
useManualHistory
} from "@usels/web";
const
const text$: any
text$
=
useObservable<unknown>(value: Promise<unknown> | (() => unknown) | unknown, deps?: React.DependencyList): any (+3 overloads)

A React hook that creates a new observable

@paraminitialValue The initial value of the observable or a function that returns the initial value

@seehttps://www.legendapp.com/dev/state/react/#useObservable

useObservable
("saved");
const {
const commit: any
commit
,
const reset: any
reset
} =
import useManualHistory
useManualHistory
(
const text$: any
text$
);
const commit: any
commit
(); // snapshot: "saved"
const text$: any
text$
.
any
set
("unsaved"); // uncommitted edit
const reset: any
reset
(); // text$ → "saved" (stacks unchanged)
import {
function useObservable<T>(): Observable<T | undefined> (+3 overloads)

A React hook that creates a new observable

@paraminitialValue The initial value of the observable or a function that returns the initial value

@seehttps://www.legendapp.com/dev/state/react/#useObservable

useObservable
} from "@legendapp/state/react";
import {
import useManualHistory
useManualHistory
} from "@usels/web";
const
const value$: any
value$
=
useObservable<unknown>(value: Promise<unknown> | (() => unknown) | unknown, deps?: React.DependencyList): any (+3 overloads)

A React hook that creates a new observable

@paraminitialValue The initial value of the observable or a function that returns the initial value

@seehttps://www.legendapp.com/dev/state/react/#useObservable

useObservable
(0);
const {
const commit: any
commit
,
const clear: any
clear
,
const history$: any
history$
} =
import useManualHistory
useManualHistory
(
const value$: any
value$
);
const value$: any
value$
.
any
set
(1);
const commit: any
commit
();
const value$: any
value$
.
any
set
(2);
const commit: any
commit
();
const clear: any
clear
(); // history$ → [{ snapshot: 2, timestamp: ... }], stacks empty
export interface UseManualHistoryOptions<Raw, Serialized = Raw> {
capacity?: number;
clone?: boolean | ((value: Raw) => Raw);
dump?: (value: Raw) => Serialized;
parse?: (value: Serialized) => Raw;
}
export interface UseManualHistoryReturn<Raw, Serialized = Raw> {
readonly canUndo$: ReadonlyObservable<boolean>;
readonly canRedo$: ReadonlyObservable<boolean>;
readonly history$: ReadonlyObservable<UseHistoryRecord<Serialized>[]>;
readonly last$: ReadonlyObservable<UseHistoryRecord<Serialized>>;
commit: Fn;
undo: Fn;
redo: Fn;
clear: Fn;
reset: Fn;
}
export declare function useManualHistory<Raw, Serialized = Raw>(source$: Observable<Raw>, options?: DeepMaybeObservable<UseManualHistoryOptions<Raw, Serialized>>): UseManualHistoryReturn<Raw, Serialized>;

View on GitHub

  • tigerwest
  • a7392ab 2026-03-06 - feat(core,browser): add sync strategy hooks (tigerwest)