fix(tables): stop insert-row flicker and return order_key from rows list#4918
Conversation
The rows insert flicker came from useCreateTableRow.onSettled invalidating tableKeys.detail(tableId), which prefix-matches the nested rowsRoot rows query and forces an un-cancelled refetch on every insert. A late offset refetch could resolve after the optimistic splice and clobber freshly-inserted rows. - invalidate detail with exact:true (+ lists) so the count surfaces refresh without cascading into the rows query - compare order keys bytewise in reconcileCreatedRow to match the server's COLLATE "C" ordering and fitsAfter (was localeCompare) - include order_key in the GET /rows list response; it was dropped in the route mapping, so the client never saw keys and reconcileCreatedRow always fell back to the position path
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview GET
Reviewed by Cursor Bugbot for commit 00db4ec. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 9c011f6. Configure here.
Greptile SummaryThis PR fixes three interconnected issues causing insert-row flicker and incorrect key-ordered placement in user tables. Together, the fixes complete the client-side half of fractional ordering by making
Confidence Score: 5/5Safe to merge; all three changes are narrowly scoped bug fixes with no new code paths introduced for un-keyed or mixed-key tables. The invalidation fix is conservative (adds No files require special attention; the changes are straightforward and internally consistent. Important Files Changed
Sequence DiagramsequenceDiagram
participant UI
participant useMutation as useCreateTableRow
participant QueryCache as React Query Cache
participant Server
UI->>useMutation: mutate(rowData)
useMutation->>Server: POST /api/table/[id]/rows
Server-->>useMutation: "{ row: { id, data, position, orderKey, ... } }"
Note over useMutation: onSuccess
useMutation->>QueryCache: "reconcileCreatedRow()<br/>(bytewise sort by orderKey<br/>OR position fallback)"
QueryCache-->>UI: "optimistic row appears<br/>(no refetch, no flicker)"
Note over useMutation: onSettled (success OR error)
useMutation->>QueryCache: "invalidateRowCountSurfaces()<br/>exact:true on detail(tableId)<br/>+ lists()"
Note over QueryCache: rows query NOT invalidated<br/>(exact:true prevents cascade<br/>into rowsRoot prefix)
QueryCache->>Server: refetch detail(tableId) only
Server-->>QueryCache: updated rowCount
QueryCache-->>UI: count badge updated
Reviews (1): Last reviewed commit: "fix(tables): stop insert-row flicker and..." | Re-trigger Greptile |
reconcileCreatedRow patched every rows query under rowsRoot, but its orderKey/position heuristic only matches the unfiltered, unsorted server order. Under a filter or column sort the splice could show wrong rows, wrong order, or an inflated totalCount, and without the prior rowsRoot refetch it persisted until the query went stale. - patch only the default-order rows queries (filter and sort both absent) - refetch the filtered/sorted variants on insert; active ones update now, inactive ones on next view. The default view stays optimistic (no flicker) - the find/write subtrees are excluded from the splice (different shape)

Summary
useCreateTableRow.onSettledinvalidatedtableKeys.detail(tableId), which prefix-matches the nestedrowsRootrows query and forced an un-cancelled refetch on every insert — a late offset refetch could resolve after the optimistic splice and clobber freshly-inserted rows. Now invalidatedetailwithexact: true(+lists()) so the count surfaces refresh without cascading into the rows query.reconcileCreatedRow(waslocaleCompare) to match the server'sCOLLATE "C"ordering and the existingfitsAfterchecks.order_keyin theGET /rowslist response — it was dropped in the route's row mapping (the POST/batch handlers already returned it), so the client never saw keys andreconcileCreatedRowalways fell back to the position path. Surfacing it activates the key-ordered path and makes insert-above/below place correctly with no refetch.Type of Change
Testing
Tested manually via Chrome DevTools against a live table:
bun run lintclean;bun run check:api-validation:strictpasses.Checklist