Skip to content

Bug: React SKD useTable isReady reverts to false after first row event #4559

@sean256

Description

@sean256

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

  1. useTable mounts, creates a subscription
  2. onApplied fires → setSubscribeApplied(true) → re-render → computeSnapshot is recreated with subscribeApplied = trueisReady briefly returns true
  3. A row event (insert/delete/update) arrives → the handler inside subscribe calls the stale computeSnapshot (still capturing subscribeApplied = false) → writes [rows, false] into lastSnapshotRef
  4. isReady drops back to false and never recovers, since nothing causes subscribe to re-capture the updated computeSnapshot

Impact

  • Any app relying on isReady for 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 their isReady isn'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,
     ]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions