Skip to content

Commit 104949b

Browse files
authored
fix(tables): eliminate checkbox flicker on rapid cell toggle (#4592)
* fix(tables): eliminate checkbox flicker on rapid cell toggle * fix(tables): symmetric guarded onSettled across row write mutations * fix(tables): merge only mutated keys in onSuccess to preserve concurrent optimistic patches
1 parent 568a552 commit 104949b

1 file changed

Lines changed: 31 additions & 6 deletions

File tree

apps/sim/hooks/queries/tables.ts

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export const tableKeys = {
8585
rowsRoot: (tableId: string) => [...tableKeys.detail(tableId), 'rows'] as const,
8686
infiniteRows: (tableId: string, paramsKey: string) =>
8787
[...tableKeys.rowsRoot(tableId), 'infinite', paramsKey] as const,
88+
rowWrites: (tableId: string) => [...tableKeys.rowsRoot(tableId), 'write'] as const,
8889
}
8990

9091
type TableRowsParams = Omit<TableRowsQueryInput, 'filter' | 'sort'> &
@@ -543,14 +544,15 @@ export function useUpdateTableRow({ workspaceId, tableId }: RowMutationContext)
543544
const queryClient = useQueryClient()
544545

545546
return useMutation({
547+
mutationKey: tableKeys.rowWrites(tableId),
546548
mutationFn: async ({ rowId, data }: UpdateTableRowParams) => {
547549
return requestJson(updateTableRowContract, {
548550
params: { tableId, rowId },
549551
body: { workspaceId, data: data as RowData },
550552
})
551553
},
552-
onMutate: ({ rowId, data }) => {
553-
void queryClient.cancelQueries({ queryKey: tableKeys.rowsRoot(tableId) })
554+
onMutate: async ({ rowId, data }) => {
555+
await queryClient.cancelQueries({ queryKey: tableKeys.rowsRoot(tableId) })
554556

555557
const previousQueries = queryClient.getQueriesData<InfiniteData<TableRowsResponse, number>>({
556558
queryKey: tableKeys.rowsRoot(tableId),
@@ -573,6 +575,24 @@ export function useUpdateTableRow({ workspaceId, tableId }: RowMutationContext)
573575

574576
return { previousQueries }
575577
},
578+
onSuccess: (response, { rowId, data: mutatedData }) => {
579+
const serverRow = response.data.row
580+
const mutatedKeys = Object.keys(mutatedData)
581+
patchCachedRows(queryClient, tableId, (row) => {
582+
if (row.id !== rowId) return row
583+
const merged: RowData = { ...row.data }
584+
for (const key of mutatedKeys) {
585+
merged[key] = (serverRow.data as RowData)[key]
586+
}
587+
return {
588+
...row,
589+
data: merged,
590+
position: serverRow.position,
591+
createdAt: serverRow.createdAt,
592+
updatedAt: serverRow.updatedAt,
593+
}
594+
})
595+
},
576596
onError: (error, _vars, context) => {
577597
if (context?.previousQueries) {
578598
for (const [queryKey, data] of context.previousQueries) {
@@ -583,7 +603,9 @@ export function useUpdateTableRow({ workspaceId, tableId }: RowMutationContext)
583603
toast.error(error.message, { duration: 5000 })
584604
},
585605
onSettled: () => {
586-
invalidateRowData(queryClient, tableId)
606+
if (queryClient.isMutating({ mutationKey: tableKeys.rowWrites(tableId) }) === 1) {
607+
invalidateRowData(queryClient, tableId)
608+
}
587609
},
588610
})
589611
}
@@ -599,6 +621,7 @@ export function useBatchUpdateTableRows({ workspaceId, tableId }: RowMutationCon
599621
const queryClient = useQueryClient()
600622

601623
return useMutation({
624+
mutationKey: tableKeys.rowWrites(tableId),
602625
mutationFn: async ({ updates }: BatchUpdateTableRowsParams) => {
603626
return requestJson(batchUpdateTableRowsContract, {
604627
params: { tableId },
@@ -608,8 +631,8 @@ export function useBatchUpdateTableRows({ workspaceId, tableId }: RowMutationCon
608631
},
609632
})
610633
},
611-
onMutate: ({ updates }) => {
612-
void queryClient.cancelQueries({ queryKey: tableKeys.rowsRoot(tableId) })
634+
onMutate: async ({ updates }) => {
635+
await queryClient.cancelQueries({ queryKey: tableKeys.rowsRoot(tableId) })
613636

614637
const previousQueries = queryClient.getQueriesData<InfiniteData<TableRowsResponse, number>>({
615638
queryKey: tableKeys.rowsRoot(tableId),
@@ -644,7 +667,9 @@ export function useBatchUpdateTableRows({ workspaceId, tableId }: RowMutationCon
644667
toast.error(error.message, { duration: 5000 })
645668
},
646669
onSettled: () => {
647-
invalidateRowData(queryClient, tableId)
670+
if (queryClient.isMutating({ mutationKey: tableKeys.rowWrites(tableId) }) === 1) {
671+
invalidateRowData(queryClient, tableId)
672+
}
648673
},
649674
})
650675
}

0 commit comments

Comments
 (0)