Next.js Discord

Discord Forum

Invalidate Data Cache on Vercel

Unanswered
Tomistoma posted this in #help-forum
Open in Discord
Avatar
TomistomaOP
I'm trying to get fresh data whenever my data refetches after a mutation, but the UI isn't updating for my users or invalidating.

Client component data Fetch:
  const { data: linkedProductView } = useQuery<LinkedProductView[]>({
    queryKey: ['linkedProductView'],
    queryFn: async () => {
      const response = await fetch('/api/linkedProductView', {
        cache: 'no-store',
        headers: {
          'Cache-Control': 'no-cache, no-store, must-revalidate',
          'Pragma': 'no-cache'
        }
      });
      
      // Force revalidation by adding timestamp
      const data = await response.json();
      return data;
    },
    staleTime: 0,
    gcTime: 0,
    refetchOnMount: true,
    refetchOnWindowFocus: true,
    refetchInterval: 5000,
  });

6 Replies

Avatar
TomistomaOP
For the UI update mutation we have an optimstic update and onSuccess we invalidate the from react query fetch:
 const verifyMutation = useMutation({
    mutationFn: verifyProductLink,

    // Update UI before server responds
    onMutate: async (linkId) => {
      // Save old state for rollback
      const previousData = queryClient.getQueryData(['linkedProductView']);
      
      // Optimistically update UI
      queryClient.setQueryData(['linkedProductView'], (old: LinkedProductView[] | undefined) => 
        old?.map(item => 
          item.linkId === linkId 
            ? { ...item, isVerified: true }
            : item
        ) || []
      );
      
      return { previousData };
    },

    // If server call fails, rollback UI
    onError: (err, variables, context: { previousData: any } | undefined) => {
      if (context) {
        queryClient.setQueryData(['linkedProductView'], context.previousData);
      }
      toast({
        variant: "destructive",
        title: "Error",
        description: "Failed to verify product",
      });
    },

    // If successful, UI is already updated
    onSuccess: () => {
      // Invalidate and refetch to sync with other sessions
      queryClient.invalidateQueries({ queryKey: ['linkedProductView'] });
      toast({
        title: "Success",
        description: "Product verified successfully",
      });
    }
  });
In the server action mutation itself we revalidate the path
'use server'
import { revalidatePath } from 'next/cache';
import { drizzle } from 'drizzle-orm/neon-http';
import { eq } from 'drizzle-orm';
import * as schema from '@/drizzle/amazon/migrations/schema';
import { neon } from "@neondatabase/serverless";

export async function verifyProductLink(linkId: number) {
  try {
    if (!process.env.NEON_DATABASE_URL) {
      throw new Error('NEON_DATABASE_URL is not defined');
    }
    
    const sql = neon(process.env.NEON_DATABASE_URL);
    const db = drizzle(sql, { schema });

    await db.update(schema.amazonShopifyProductLinks)
      .set({ isVerified: true })
      .where(eq(schema.amazonShopifyProductLinks.id, linkId));

    revalidatePath('/sku-sync', 'page');
  

    return { success: true };
    
  } catch (error) {
    console.error('Failed to verify product link:', error);
    return { success: false, error: (error as Error).message };
  }
}
Avatar
Least Storm-Petrel
Does it refetch every 5s with the new data after the mutation?

If yes, just try to trigger a refetch instead of an invalidate. The query should already be marked as stale because of the query's settings, I think.

(btw for code blocks you can add a language identifier, e.g. ts after the 3 ticks ```ts which makes it syntax highlight)
I added two lines to my server action which worked to skip the cache and then the refetch worked
Ill post actualy lines i added