-
Notifications
You must be signed in to change notification settings - Fork 869
Open
Description
Summary
The React useTable hook's isReady boolean correctly flips to true when onApplied fires, but reverts to false on the very next row insert/delete/update event and stays stuck there permanently.
Root Cause
The subscribe callback passed to useSyncExternalStore calls computeSnapshot() inside its onInsert/onDelete/onUpdate handlers, but computeSnapshot was not listed in subscribe's useCallback dependency array. This means subscribe captured a stale computeSnapshot closure that permanently held subscribeApplied = false.
Reproduction sequence
useTablemounts, creates a subscriptiononAppliedfires →setSubscribeApplied(true)→ re-render →computeSnapshotis recreated withsubscribeApplied = true→isReadybriefly returnstrue- A row event (insert/delete/update) arrives → the handler inside
subscribecalls the stalecomputeSnapshot(still capturingsubscribeApplied = false) → writes[rows, false]intolastSnapshotRef isReadydrops back tofalseand never recovers, since nothing causessubscribeto re-capture the updatedcomputeSnapshot
Impact
- Any app relying on
isReadyfor something like, handling stale data, loaders, etc, will not function properly - Only affects the React hook — Svelte and Vue versions use mutable refs (
writable/ref) so theirisReadyisn't captured in a stale closure
Fix
Add computeSnapshot to the subscribe dependency array in src/react/useTable.ts:
[
connectionState,
accessorName,
querySql,
+ computeSnapshot,
callbacks?.onDelete,
callbacks?.onInsert,
callbacks?.onUpdate,
]Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels