Site index
Arrow keys to navigateEnter to open / Esc to close
Writing index
Field note / Frontend engineering

From static to dynamic: using TanStack Query for real-time data in Next.js

How to layer client-side caching and background refresh on top of a static Next.js page with TanStack Query.

1 min readnext.jstanstack-querydatacaching
On this page
From static to dynamic: using TanStack Query for real-time data in Next.js

Static pages are fast, but some data changes while the user is looking at it. TanStack Query gives you caching, background refresh, and loading states without rewriting your routing model.

The mental model

Think in three states: fresh, stale, and background.

  • Fresh: use the cache, do not refetch
  • Stale: show the cache, refetch in the background
  • Missing: show a loading state, fetch

You only configure how long something stays fresh.

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 60_000,
      gcTime: 5 * 60_000,
      retry: 2,
      refetchOnWindowFocus: false,
    },
  },
});

A query with a clear key

The query key is the cache identity. Include everything the result depends on.

function useProjects(category: string) {
  return useQuery({
    queryKey: ["projects", category],
    queryFn: async () => {
      const res = await fetch(`/api/projects?category=${category}`);
      if (!res.ok) throw new Error("Request failed");
      return res.json();
    },
  });
}

Notice the res.ok check. fetch only rejects on network failure, never on a 500.

Mutations that update the cache

After a write, either invalidate the affected queries or update them directly.

const mutation = useMutation({
  mutationFn: createProject,
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: ["projects"] });
  },
});

Keep the server boundary honest

Do not move everything to the client. Fetch what changes often on the client and keep the rest server-rendered.

DataWhere
Marketing copy, metadataServer
User-specific, frequently changingClient, via TanStack Query
Initial page render payloadServer, then hydrate

The best real-time experience is the one that still renders instantly on a slow connection.

Cache aggressively, refresh quietly, and show the last known value while you do it.

Continue reading

Related articles

Modal interface

Accent system

Choose a palette. The selection is saved on this device.

Accent color themes

28 palettes available

Modal interface

A note worth keeping

A randomly selected thought from the inspiration archive.