v0.2.1
React bindings hardening. Fixes two infinite-loop classes that surfaced in downstream apps as React error #185 (“Maximum update depth exceeded”), and exposes sync-status reactivity as a first-class observable + hook.
Fixed
useQuery/useOneno longer loop ongetSnapshot. TheuseSyncExternalStoreadapter was returning a freshview.results.slice()on every call, which React’s post-commit consistency check interpreted as “store updated mid-render” — scheduling another render, another snapshot, another mismatch, ad infinitum. The snapshot is now cached in a ref and only refreshed inside the subscribe callback right beforeonChange()fires. Affected every tree with multiple simultaneoususeQuerysubscribers.
Added
BaseSyncedStoresync status is now properly observable.syncStatusanddataReadyare annotatedobservable;isReady,isSyncing,isOffline,isReconnecting,isError,hasUnsyncedChangesarecomputed. Before, these were plain getters over plain fields —reaction(() => store.isReady, ...)silently never fired. Existingobserver/reactioncall sites that relied on the implicitpool.sizetrigger will continue to work; new call sites should read these observables directly.useSyncStatus()React hook. Returns{ isReady, isSyncing, isOffline, isReconnecting, isError, hasUnsyncedChanges }as a reactive snapshot, bridged viauseSyncExternalStorewith a correctly-cached snapshot. Replaces hand-rolledreactionbridges in consumer providers. Seedocs/react.md.SyncStoreContractsurfaces the status getters so TypeScript autocomplete works from theuseSyncContext()return value without a cast.
Documentation
llms.txtanddocs/react.mdgained a “Common pitfalls” section covering the three traps this release addresses: don’t wrap providers inobserver(),getSnapshotmust return a cached reference, and sync-status fields are real observables (don’t watchpool.sizeas a proxy).
Migration
No breaking changes. Optional: replace any local reaction(() => store.isReady, setReady, { fireImmediately: true }) bridges in your own providers with const { isReady } = useSyncStatus() for consumers below the store provider.