I use optimistic updates for the UI and it works, but the data is not re-fetched. In the server terminal I see only a DELETE request. There should be a GET right after it
queryClient.js
import { QueryClient } from "@tanstack/react-query";
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 0, // Data is fresh for 0 milliseconds (default)
gcTime: 300000, // Cache inactive data for 5 minutes
refetchOnWindowFocus: false, // Disable refetch on window focus
refetchOnReconnect: true, // Refetch on reconnecting to the internet
retry: 2, // Retry failed queries twice before throwing an error
retryDelay: 3000, // Wait 3 seconds between retries
refetchInterval: false, // No polling by default
},
mutations: {
retry: 2, // Retry failed mutations twice
useErrorBoundary: true, // Use React Error Boundary for mutation errors
},
},
});
// Set specific defaults for "products" query
queryClient.setQueryDefaults(["products"], {
staleTime: 0, // Data is considered fresh for 0 milliseconds
gcTime: 300000, // Cache inactive data for 30 minutes
refetchOnWindowFocus: true, // Enable refetch on window focus
refetchOnMount: "always", // Always re-fetch after invalidation when component mounts
refetchOnReconnect: true, // Refetch on reconnecting to the internet
retry: 2, // Retry failed queries twice before throwing an error
retryDelay: 3000, // Wait 3 seconds between retries
});
export default queryClient;
fetch products in Home.jsx after db is seeded
// Fetch products and store in cache
useQuery({
queryKey: ["products"], // Unique key for caching
queryFn: getAllProducts, // Function to fetch products
enabled: isSeeded, //fetch only if database is hydrated
});
useDeleteProductsHook.js
onSettled() logs after invalidation but invalidation doesn't work
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { deleteProductService } from "../services/productServices";
import toast from "react-hot-toast";
export function useDeleteProduct() {
const queryClient = useQueryClient();
const { isLoading: isDeleting, mutate: deleteProduct } = useMutation({
mutationFn: deleteProductService, // Function to perform the mutation
// Optimistic update: Modify cache before mutation
onMutate: async (productId) => {
// Cancel any outgoing re-fetches for "products"
await queryClient.cancelQueries(["products"]);
// Snapshot of previous products for rollback
const previousProducts = queryClient.getQueryData(["products"]);
// Optimistically update cache by removing the product
queryClient.setQueryData(["products"], (oldProducts) => {
const updatedProducts = oldProducts.filter(
(product) => product._id !== productId,
);
return [...updatedProducts];
});
// Return context with snapshot for rollback
return { previousProducts };
},
// Rollback if mutation fails
onError: (err, productId, context) => {
queryClient.setQueryData(["products"], context.previousProducts); // Restore previous state
toast.error(err.message);
},
// Always refetch after mutation (success or failure)
onSettled: () => {
queryClient.invalidateQueries("products");
// log is being reached
console.log("invalidation");
},
// Success-specific actions
onSuccess: () => {
toast.success("Product deleted successfully");
},
});
return { isDeleting, deleteProduct };
}