ServicesContactCall Us Today
Call Us Today
ServicesContact
Back to blog

March 18, 2025

Data Fetching with TanStack Query

How TanStack Query handles caching, background refetching, and optimistic updates to make your UI feel instant.

Data Fetching with TanStack Query

On this page

What TanStack Query doesuseQueryuseMutation with cache invalidationOptimistic updatesPrefetching on the server

What TanStack Query does

TanStack Query (formerly React Query) manages server state — data that lives on a remote server and needs to be fetched, cached, and kept in sync. It handles loading states, error states, background refetching, and cache invalidation so you don't have to.

In this stack, it's paired with tRPC so every procedure gets full query/mutation support with zero configuration.

useQuery

"use client";
 
import { useQuery } from "@tanstack/react-query";
import { useTRPC } from "@/services/trpc/client";
 
const PostList = () => {
  const trpc = useTRPC();
  const { data, isPending, isError } = useQuery(
    trpc.posts.list.queryOptions()
  );
 
  if (isPending) return <Skeleton className="h-40 w-full" />;
  if (isError) return <p className="text-destructive">Failed to load posts.</p>;
 
  return (
    <ul className="flex flex-col gap-4">
      {data.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
};

useMutation with cache invalidation

After a mutation succeeds, invalidate the relevant query so the list refreshes automatically:

const trpc = useTRPC();
const queryClient = useQueryClient();
 
const deletePost = useMutation(
  trpc.posts.delete.mutationOptions({
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: trpc.posts.list.queryKey() });
      toast.success("Post deleted");
    },
    onError: () => toast.error("Something went wrong"),
  })
);

Optimistic updates

For instant UI feedback before the server responds:

const toggleLike = useMutation(
  trpc.posts.toggleLike.mutationOptions({
    onMutate: async ({ postId }) => {
      await queryClient.cancelQueries({ queryKey: trpc.posts.list.queryKey() });
      const previous = queryClient.getQueryData(trpc.posts.list.queryKey());
      queryClient.setQueryData(trpc.posts.list.queryKey(), (old) =>
        old?.map((p) => p.id === postId ? { ...p, liked: !p.liked } : p)
      );
      return { previous };
    },
    onError: (_err, _vars, ctx) => {
      queryClient.setQueryData(trpc.posts.list.queryKey(), ctx?.previous);
    },
  })
);

Prefetching on the server

Prefetch queries in a Server Component and pass the dehydrated state to the client to avoid a loading flicker:

// app/posts/page.tsx (Server Component)
import { HydrationBoundary, dehydrate } from "@tanstack/react-query";
import { createQueryClient } from "@/services/trpc/query-client";
 
export default async function PostsPage() {
  const queryClient = createQueryClient();
  await queryClient.prefetchQuery(trpc.posts.list.queryOptions());
 
  return (
    <HydrationBoundary state={dehydrate(queryClient)}>
      <PostList />
    </HydrationBoundary>
  );
}

The client hydrates instantly with data already in the cache — no loading spinner on first paint.

Let's Get In Touch.

Your laboratory instruments should serve you, not the other way around. We're happy to help you.

Call Us Today Contact Us

Transforming houses into dream homes with quality craftsmanship and exceptional service.

Quick Links

  • Services
  • Privacy Policy

Contact Us

  • +15036066416
  • contact@samadihomerenovation.com

Location

Portland Oregon 97223

Our Services

  • Kitchen Remodeling
  • Bathroom Renovation
  • Doors & Windows
  • Handyman Services
  • Flooring Installation
  • Interior Painting

© 2025 Samadi Home Renovation LLC. All rights reserved.

Licensed & Bonded & Insured