CL Sync provides a set of React hooks that subscribe to store changes and keep your components in sync with local-first data. All hooks must be used inside a SyncProvider. They re-render automatically whenever the relevant slice of store state changes.
useSyncStatus()
Returns the live SyncStatus object. Use it to show loading states, connection indicators, and pending mutation counts. The component re-renders whenever any status field changes.
useSyncCollection(definition, args?)
Subscribes to a collection slice and returns the sorted record array. Returns undefined while the store has never loaded this slice (distinct from [], which means the server confirmed it’s empty). Pass query arguments when your collection uses deriveKey.
Use ?? [] to fall back to an empty array before hydration completes. Use ?? undefined and render a skeleton when you want to distinguish “not loaded yet” from “loaded but empty”.
useSyncRecord(collection, id?)
Subscribes to a single record by collection name and string ID. Returns undefined if the record isn’t in the cache or if id is undefined (handy for optional IDs from route params).
useSyncMutation(definition)
Returns a stable callback that calls store.enqueueMutation when invoked. The callback applies the optimistic reducer immediately and returns a promise that resolves with the flush result (or undefined if no flush is defined).
The returned callback signature is:
useHydratedValue(localValue, serverValue)
A utility hook for server-rendering patterns. Returns:
serverValue if it is non-nullish (server data is authoritative)
localValue if the store is hydrated (IndexedDB data is ready)
undefined if neither is available yet
This pattern lets you pass server-rendered data as a prop for the initial paint, then seamlessly hand off to the local cache once it’s ready.
useSyncStore()
Returns the raw SyncStore instance from context. Use this for advanced patterns that need direct store access outside the higher-level hooks.
useSyncSelector(selector)
Subscribes to store changes and returns the result of selector(store). The component re-renders only when the selector’s return value changes (by reference equality). Use this for custom derived state that doesn’t map directly to a single collection or record.
useSyncSelector re-runs the selector on every store emission. Keep selectors cheap — avoid allocating new arrays or objects inside the selector unless you memoize with useMemo.