Skip to content
GitHub

TanStack Query

Automatic caching, background refetching, and request deduplication for server state.

Without TanStack Query:

  • Manual loading/error state
  • No caching (refetch on every mount)
  • Race conditions
  • Lots of boilerplate

With TanStack Query:

const { data, isLoading } = useTasks(); // Done.

Automatic caching, refetching, deduplication, and loading states.

app/providers.tsx       # QueryClient setup
lib/api/tasks.ts        # API functions
hooks/use-tasks.ts      # TanStack Query hooks
components/tasks.tsx    # Use hooks

1. API Function (lib/api/tasks.ts):

export async function getTasks(): Promise<TasksListResponse> {
  return api.get<TasksListResponse>("/tasks");
}

2. Hook (hooks/use-tasks.ts):

export const tasksKeys = { all: ["tasks"] };

export function useTasks() {
  return useQuery({
    queryKey: tasksKeys.all,
    queryFn: getTasks,
  });
}

export function useCreateTask() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: createTask,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: tasksKeys.all });
    },
  });
}

3. Component:

function TasksList() {
  const { data, isLoading } = useTasks();
  const createTask = useCreateTask();

  if (isLoading) return <Spinner />;
  return <div>{data.tasks.map(task => <TaskItem {...task} />)}</div>;
}
  • Automatic caching - Multiple components share same data
  • Background refetch - Updates on window focus/network reconnect
  • Request deduplication - One request for multiple consumers
  • Optimistic updates - Instant UI feedback

See TanStack Query docs for more.