Data fetching e cache
Buscar dado direto no componente de servidor, e por que TanStack Query entra no client depois disso.
No servidor: fetch direto no componente
Como a página inteira já roda no servidor por padrão (lição anterior), buscar dado é só um await dentro do componente — sem useEffect, sem estado de loading manual.
async function getProdutos() {
const res = await fetch("https://api.exemplo.com/produtos", {
next: { revalidate: 60 }, // cache por 60s, depois revalida
});
return res.json();
}
export default async function ProdutosPage() {
const produtos = await getProdutos();
return <ProdutosList produtos={produtos} />;
}next: { revalidate: 60 } é o cache do próprio Next.js: a resposta fica guardada por 60 segundos antes de buscar de novo, sem você escrever lógica de cache nenhuma.
No client: por que ainda existe TanStack Query
Fetch no servidor resolve a carga inicial da página. Mas e uma ação do usuário depois disso — curtir um post, editar um formulário, recarregar uma lista sem dar refresh na página inteira? Isso já é interação, então já é client-side — e é aí que entra o TanStack Query: cache de requisição no navegador, invalidação, retry automático, sem reinventar isso na mão.
"use client";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
function usePosts() {
return useQuery({ queryKey: ["posts"], queryFn: () => fetch("/api/posts").then((r) => r.json()) });
}
function useLikePost() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => fetch(`/api/posts/${id}/like`, { method: "POST" }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ["posts"] }),
});
}A regra prática: fetch direto no servidor pra carga inicial de página; TanStack Query pra qualquer coisa que precisa reagir a uma ação do usuário depois que a página já carregou.