Replies: 3 comments
-
|
Use case: Requirements:
|
Beta Was this translation helpful? Give feedback.
-
|
yolo |
Beta Was this translation helpful? Give feedback.
-
|
When trying to build out a collections-level queue solution using usePacedMutation, this is the first issue I am struggling with: how to trigger a sync from within a usePacedMutation mutationFn considering I don't want to refetch after mutation completed. If I optimistically update from within a usePacedMutation onMutate callback, do I need to refetch when the mutation completes in order to discard my optimistic update? const mutateAnnotation = usePacedMutations<{
type: 'insert' | 'update' | 'delete';
id: string;
data?: Partial<Annotation>;
}>({
onMutate: ({ type, id, data }) => {
if (type === 'insert') {
// Optimistically insert the new annotation into the mutations store
// This uses a temporary ID generated on the client
annotationsCollection.insert(data);
} else if (type === 'update') {
annotationsCollection.update(id, draft => {
draft.coords = data.coords;
});
} else if (type === 'delete') {
annotationsCollection.delete(id);
}
},
mutationFn: async ({ transaction }) => {
const mutation = transaction.mutations[0];
if (mutation.type === 'insert') {
const response = await axios.post(`/annotation`, mutation.changes);
// Manage IDs
const realId = response.data.id;
const tempId = mutation.changes.id;
linkIds(tempId, realId);
idMap.set(tempId, realId);
// After getting the real ID from the server, we write it to the synced store
// But how can we trigger a sync from within a pacedMutation mutationFn
// so as to clear the tempId item from the mutations store
annotationsCollection.utils.writeInsert({
...mutation.changes,
id: realId
});
// Result: mutations store still contains the item with tempId
// and synced store now has the item with realId, resulting in 2 items in UI
// Why doesn't the completion of mutationFn trigger a sync that would
// reconcile these two stores and remove the temporary mutation?
} else if (mutation.type === 'update') {
const id = getResolvedId(mutation.original.id);
await axios.put(`/annotation/${id}`, mutation.changes);
annotationsCollection.utils.writeUpdate(mutation.modified);
} else if (mutation.type === 'delete') {
const id = getResolvedId(mutation.original.id);
await axios.delete(`/annotation/${id}`);
annotationsCollection.utils.writeDelete(id);
}
},
strategy: queueStrategy({
wait: 0,
addItemsTo: 'back',
getItemsFrom: 'front'
})
});
const handleCreate = async (id, data) => {
mutateAnnotation({
type: 'insert',
id: id,
data: {...data} // Created data
});
};
const handleUpdate = (id, data) => {
mutateAnnotation({
type: 'update',
id: id,
data: {...data } // Updated data
});
};
const handleDelete = (id) => {
mutateAnnotation({
type: 'delete',
id: id
});
}; |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
TanStack Query has mutation scopes that allow mutations to be paused, canceled, or resumed based on scope. As far as I can tell TanStack DB collections don't have an equivalent, making it difficult to coordinate mutations across different operation types (create/update/delete) for the same item.
Use case: An annotation tool where users rapidly create, modify, and delete shapes within seconds. Without mutation scopes, update and delete mutations can fire before the create request returns the real ID from the server, causing these subsequent operations to fail. It wouldn't be acceptable UX to block user actions waiting for requests to resolve - drawing actions fire immediately with queuing and syncing happening transparently in the background.
How would queued mutations access updated collection data (like real IDs) from previous mutations in the same scope? Would the onUpdate handler only get called when the mutation is actually being executed from the queue? If so, would it have access to the updated collection state from previously completed mutations in the same scope?
With mutation scopes, would it be:
Essentially, this would be a shared scope across mutation operations, or a shared queue strategy where each mutation waits for previous mutations in the scope to complete and sync before executing. Or what about scopes at the collection level, or a queue strategy at the collection level?
Is this already possible with Tanstack DB?
Beta Was this translation helpful? Give feedback.
All reactions