SharedStore
Type Parameters
Section titled “Type Parameters”| Type Parameter |
|---|
S extends Record<string, unknown> |
Properties
Section titled “Properties”clientId
Section titled “clientId”readonly clientId: string;hydrated
Section titled “hydrated”readonly hydrated: Promise<void>;Resolves once persisted state has been restored — or refused, or found
absent. Already resolved when there is no persist option at all.
Exists because an async adapter cannot hydrate before the store is handed back, and until now that gap was unobservable: a keystroke landing in it writes at counter 1, the restore arrives holding counter 5, and last-writer-wins correctly discards the newer keystroke. The behaviour is right and the surprise is total. Gate first paint or first input on this and the gap closes:
await store.hydrated;Never rejects. A refused restore is reported through
persist.onRestoreError and still settles, because a store that kept its
initial values is usable and a promise nobody can await is not.
readonly state: S;Live proxy for imperative use: store.state.count++ syncs everywhere.
Methods
Section titled “Methods”close()
Section titled “close()”close(): void;Returns
Section titled “Returns”void
getSnapshot()
Section titled “getSnapshot()”getSnapshot(): Readonly<S>;Immutable snapshot, replaced whenever a change is applied. Safe for useSyncExternalStore.
Returns
Section titled “Returns”Readonly<S>
getVersions()
Section titled “getVersions()”getVersions(): Readonly<Record<string, Version>>;The per-key version clocks behind the snapshot. Referentially stable, like getSnapshot.
Returns
Section titled “Returns”Readonly<Record<string, Version>>
registerKey()
Section titled “registerKey()”registerKey<K>(key, initial): void;Register a key lazily at version [0, clientId] — any patch or snapshot a peer has already made for it wins over the initial value. No-op if the key already exists.
Type Parameters
Section titled “Type Parameters”| Type Parameter |
|---|
K extends string |
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
key | K |
initial | S[K] |
Returns
Section titled “Returns”void
set<K>(key, value): void;Type Parameters
Section titled “Type Parameters”| Type Parameter |
|---|
K extends string |
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
key | K |
value | S[K] | ((prev) => S[K]) |
Returns
Section titled “Returns”void
subscribe()
Section titled “subscribe()”subscribe(fn): () => void;Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
fn | (key, value, meta) => void |
Returns
Section titled “Returns”() => void
subscribeKey()
Section titled “subscribeKey()”subscribeKey(key, fn): () => void;Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
key | keyof S & string |
fn | () => void |
Returns
Section titled “Returns”() => void
transaction()
Section titled “transaction()”transaction<T>(fn): T;Apply several writes, then notify subscribers once with the settled state.
store.transaction(() => { store.set('firstName', 'Ada'); store.set('lastName', 'Lovelace');});Local batching, not a distributed transaction. Each write is still its own patch on the wire, so a peer may see them arrive separately — making them atomic across tabs would need a wire type older builds would silently ignore, which is worse than the problem. What this buys is one re-render instead of N, and subscribers that never observe a half-applied group.
Nests: only the outermost call flushes. Returns whatever fn returns, and
flushes even if fn throws — the writes that did land are already real.
Type Parameters
Section titled “Type Parameters”| Type Parameter |
|---|
T |
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
fn | () => T |
Returns
Section titled “Returns”T