1

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 };
}

1 Answer 1

0
        queryClient.invalidateQueries("products");

Key "products" is incorrect, because you specify in

` useQuery({
        queryKey: ["products"], // Unique key for caching
        queryFn: getAllProducts, // Function to fetch products
        enabled: isSeeded, //fetch only if database is hydrated
    });`

queryKey: ["products"] not "products".

So you can try this:

        queryClient.invalidateQueries(["products"]); 

You should specify keys in array

Sign up to request clarification or add additional context in comments.

9 Comments

I've tried that, before I posted here, doesn't work. Thanks for the response
queryClient.invalidateQueries(["products"], { refetchActive: true, refetchInactive: true }); And try this option, maybe after you update the cache, invalidation does not work because it considers the cache to be relevant. This option will force a forced re-request of data
If this does not help, try to view which caches you have active, whether the cache disappears after invalidation, perhaps later setQueryDefaults - the key changes and you need to invalidate another key console.log(queryClient.getQueryCache());
@Georgios, Could you show the component where useQuery is used? Maybe there are problems there, why data is not refetching after invalidation
it re-fetches the data by adding queryClient.refetchQueries(["products"]); after invalidation. Thanks for taking the time to look into it
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.