useStorageSubscribe
The default way to read a storage reactively. useSyncExternalStore under the hood (Concurrent-safe),
no RxJS. Re-renders the component when the selected slice changes. See also the Reactive
reads overview. The examples use the end-to-end todoStorage
(TodoState = { todos: Todo[]; filter: Filter }).
Basic usage
For primitive slices it de-dupes automatically via Object.is — no needless re-renders.
import { useStorageSubscribe } from 'synapse-storage/react'
// primitive slice — de-duped automatically
const filter = useStorageSubscribe(todoStorage, (s) => s.filter)Object and array slices: equals
When the selector returns an object/array (a new reference every tick) or you want to re-render only when
a specific slice changes, pass equals. It keeps a stable snapshot and skips needless re-renders even
when the rest of the store changes.
// an unrelated store change won't re-render the component until `todos` changes by reference
const todos = useStorageSubscribe(todoStorage, (s) => s.todos, {
equals: (a, b) => a === b,
})equals returns true when the slices are "equal" — then the snapshot keeps its reference and there is
no re-render.
Notes
useSyncExternalStoregives correct behavior in Concurrent Mode (no tearing).Accepts
IStorageBase— the shared interface of sync and async storages; the subscription is the same for all types.Before init you can pass
nullinstead of the storage — the hook returnsundefined.Need RxJS operators on top of the stream? That's useStorageObservable. Reading a
SelectorAPI? That's useSelector. Need to read without a re-render in a handler?todoStorage.getStateSync()— see the overview.