TanStack Query
Await mutateAsync() in the runner. Keep cache invalidation and query state in TanStack Query, and choose one owner for user-facing notifications to avoid duplicate toasts.
const mutation = useMutation({ mutationFn: updateProfile });
const queryClient = useQueryClient();
const flow = useSubmitFlow({
save: {
run: async (input: ProfileInput) => {
const result = await mutation.mutateAsync(input);
await queryClient.invalidateQueries({ queryKey: ["profile"] });
return result;
},
success: "Profile updated.",
},
});
If the mutation already reports success and errors through callbacks, suppress those notifications or set the flow action to feedback: 'none'. Keep retry policy in the query layer and avoid automatically retrying non-idempotent writes. TanStack Query is not bundled or installed in the docs app; this is an integration recipe.
The mutation example shows the same division of responsibility without requiring a query client.