mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
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
This commit is contained in:
@@ -85,6 +85,7 @@ export const tableKeys = {
|
||||
rowsRoot: (tableId: string) => [...tableKeys.detail(tableId), 'rows'] as const,
|
||||
infiniteRows: (tableId: string, paramsKey: string) =>
|
||||
[...tableKeys.rowsRoot(tableId), 'infinite', paramsKey] as const,
|
||||
rowWrites: (tableId: string) => [...tableKeys.rowsRoot(tableId), 'write'] as const,
|
||||
}
|
||||
|
||||
type TableRowsParams = Omit<TableRowsQueryInput, 'filter' | 'sort'> &
|
||||
@@ -543,14 +544,15 @@ export function useUpdateTableRow({ workspaceId, tableId }: RowMutationContext)
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
mutationKey: tableKeys.rowWrites(tableId),
|
||||
mutationFn: async ({ rowId, data }: UpdateTableRowParams) => {
|
||||
return requestJson(updateTableRowContract, {
|
||||
params: { tableId, rowId },
|
||||
body: { workspaceId, data: data as RowData },
|
||||
})
|
||||
},
|
||||
onMutate: ({ rowId, data }) => {
|
||||
void queryClient.cancelQueries({ queryKey: tableKeys.rowsRoot(tableId) })
|
||||
onMutate: async ({ rowId, data }) => {
|
||||
await queryClient.cancelQueries({ queryKey: tableKeys.rowsRoot(tableId) })
|
||||
|
||||
const previousQueries = queryClient.getQueriesData<InfiniteData<TableRowsResponse, number>>({
|
||||
queryKey: tableKeys.rowsRoot(tableId),
|
||||
@@ -573,6 +575,24 @@ export function useUpdateTableRow({ workspaceId, tableId }: RowMutationContext)
|
||||
|
||||
return { previousQueries }
|
||||
},
|
||||
onSuccess: (response, { rowId, data: mutatedData }) => {
|
||||
const serverRow = response.data.row
|
||||
const mutatedKeys = Object.keys(mutatedData)
|
||||
patchCachedRows(queryClient, tableId, (row) => {
|
||||
if (row.id !== rowId) return row
|
||||
const merged: RowData = { ...row.data }
|
||||
for (const key of mutatedKeys) {
|
||||
merged[key] = (serverRow.data as RowData)[key]
|
||||
}
|
||||
return {
|
||||
...row,
|
||||
data: merged,
|
||||
position: serverRow.position,
|
||||
createdAt: serverRow.createdAt,
|
||||
updatedAt: serverRow.updatedAt,
|
||||
}
|
||||
})
|
||||
},
|
||||
onError: (error, _vars, context) => {
|
||||
if (context?.previousQueries) {
|
||||
for (const [queryKey, data] of context.previousQueries) {
|
||||
@@ -583,7 +603,9 @@ export function useUpdateTableRow({ workspaceId, tableId }: RowMutationContext)
|
||||
toast.error(error.message, { duration: 5000 })
|
||||
},
|
||||
onSettled: () => {
|
||||
invalidateRowData(queryClient, tableId)
|
||||
if (queryClient.isMutating({ mutationKey: tableKeys.rowWrites(tableId) }) === 1) {
|
||||
invalidateRowData(queryClient, tableId)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -599,6 +621,7 @@ export function useBatchUpdateTableRows({ workspaceId, tableId }: RowMutationCon
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
mutationKey: tableKeys.rowWrites(tableId),
|
||||
mutationFn: async ({ updates }: BatchUpdateTableRowsParams) => {
|
||||
return requestJson(batchUpdateTableRowsContract, {
|
||||
params: { tableId },
|
||||
@@ -608,8 +631,8 @@ export function useBatchUpdateTableRows({ workspaceId, tableId }: RowMutationCon
|
||||
},
|
||||
})
|
||||
},
|
||||
onMutate: ({ updates }) => {
|
||||
void queryClient.cancelQueries({ queryKey: tableKeys.rowsRoot(tableId) })
|
||||
onMutate: async ({ updates }) => {
|
||||
await queryClient.cancelQueries({ queryKey: tableKeys.rowsRoot(tableId) })
|
||||
|
||||
const previousQueries = queryClient.getQueriesData<InfiniteData<TableRowsResponse, number>>({
|
||||
queryKey: tableKeys.rowsRoot(tableId),
|
||||
@@ -644,7 +667,9 @@ export function useBatchUpdateTableRows({ workspaceId, tableId }: RowMutationCon
|
||||
toast.error(error.message, { duration: 5000 })
|
||||
},
|
||||
onSettled: () => {
|
||||
invalidateRowData(queryClient, tableId)
|
||||
if (queryClient.isMutating({ mutationKey: tableKeys.rowWrites(tableId) }) === 1) {
|
||||
invalidateRowData(queryClient, tableId)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user