Busque em todas as páginas da documentação
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Use o hook useSWR com uma chave e uma função fetcher para buscar, cachear e revalidar dados remotos declarativamente em componentes React.
"use client";
import useSWR from "swr";
const fetcher = (url: string) => fetch(url).then((res) => res.json());
function Dashboard() {
const { data, error, isLoading, isValidating } = useSWR("/api/dashboard", fetcher);
if (isLoading) return <p>Carregando...</p>;
if (error) return <p>Erro: {error.message}</p>;
return (
<div>
<h1>{data.title}</h1>
{isValidating && <span>Atualizando...</span>}
</div>
);
}"use client";
import useSWR from "swr";
interface User {
id: number;
name: string;
email: string;
}
const fetcher = (url: string): Promise<User[]> =>
fetch(url).then((res) => {
if (!res.ok) throw new Error("A resposta da rede não foi ok");
return res.json();
});
export default function UserList() {
const { data: users, error, isLoading } = useSWR<User[]>("/api/users", fetcher);
if (isLoading) return <div className="skeleton" />;
if (error) return <div role="alert">Falha ao carregar usuários</div>;
return (
<ul>
{users?.map((user) => (
<li key={user.id}>
{user.name} - {user.email}
</li>
))}
</ul>
);
}useSWR é a chave - uma string única (ou array, ou null) que identifica a requisição e controla o cache.isLoading é true apenas na primeira carga, quando ainda não há dados cacheados.isValidating é true sempre que uma requisição está em andamento, incluindo revalidações em segundo plano.dedupingInterval (padrão: 2000ms).Chaves de array (fetcher com múltiplos argumentos):
const fetcher = ([url, token]: [string, string]) =>
fetch(url, { headers: { Authorization: `Bearer ${token}` } }).then((r) => r.json());
const { data } = useSWR(["/api/user", token], fetcher);Usando axios:
import axios from "axios";
const fetcher = (url: string) => axios.get(url).then((res) => res.data);
const { data } = useSWR("/api/posts", fetcher);Fetcher GraphQL:
const fetcher = (query: string) =>
fetch("/api/graphql", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query }),
})
.then((res) => res.json())
.then((json) => json.data);
const { data } = useSWR("{ user { name } }", fetcher);useSWR para tipar o retorno: useSWR<Data, Error>(key, fetcher).Data.string, [string, ...args], ou uma função que retorne um dos dois.import useSWR, { Fetcher } from "swr";
const fetcher: Fetcher<User[], string> = (url) =>
fetch(url).then((r) => r.json());
const { data } = useSWR<User[]>("/api/users", fetcher);
// data é User[] | undefineduseSWR([url, id], ...)) é aceitável porque SWR serializa chaves de array internamente, mas chaves de objeto não são suportadas.res.ok no seu fetcher.data é undefined durante a carga inicial. Sempre trate o estado de carregamento ou use encadeamento opcional.useSWR em um Server Component resultará em erro. Hooks SWR são apenas para o lado do cliente.| Abordagem | Prós | Contras |
|---|---|---|
| useSWR | Cacheamento automático, deduplicação, revalidação | Apenas cliente, tamanho extra do bundle |
| fetch em useEffect | Sem dependências | Sem cacheamento, condições de corrida, boilerplate |
| React Query (TanTanStack) | Funcionalidades similares, mais mutações embutidas | Superfície de API maior |
| Server Components fetch | Zero JS no cliente, cacheado no servidor | Sem atualizações em tempo real |
De uma aplicação SaaS de produção Next.js 15 / React 19 (SystemsArchitect.io).
// Exemplo de produção: Busca com SWR + debouncing
// Arquivo: src/hooks/use-search.ts
export function useSearch() {
const [debouncedQuery, setDebouncedQuery] = useState(query);
useEffect(() => {
const timer = setTimeout(() => setDebouncedQuery(query), 300);
return () => clearTimeout(timer);
}, [query]);
const shouldFetch = debouncedQuery.length >= 3;
const apiUrl = shouldFetch
? `/api/search?q=${encodeURIComponent(debouncedQuery)}&platform=${platform}`
: null;
const { data, error, isLoading, isValidating } = useSWR<SearchResponse>(
apiUrl,
fetcher,
{
revalidateOnFocus: false,
revalidateOnReconnect: false,
dedupingInterval: 5000,
keepPreviousData: true,
}
);
return useMemo(() => ({
results: data?.results,
isLoading: isLoading || (shouldFetch && isValidating),
}), [data, isLoading, shouldFetch, isValidating]);
}O que isso demonstra em produção:
null como chave SWR impede completamente a busca. Esta é a maneira idiomática de buscar condicionalmente: quando shouldFetch é falso, a URL é null e SWR pula a requisição.keepPreviousData: true preserva os resultados de busca anteriores enquanto uma nova consulta está em andamento, evitando um flash de tela em branco entre as transições de chave.dedupingInterval: 5000 impede requisições duplicadas para a mesma chave dentro de 5 segundos. Se o usuário digitar "react", deletar e digitar "react" novamente em 5 segundos, SWR retornará o resultado cacheado em vez de acionar a API.revalidateOnFocus: false e revalidateOnReconnect: false desativam a revalidação automática em segundo plano. Para buscas, resultados stale são aceitáveis e revalidar ao focar na aba seria surpreendente para os usuários.useMemo no objeto de retorno impede que os componentes consumidores re-renderizem quando o estado interno do hook muda, mas os valores retornados não mudaram.isLoading (primeira carga) com isValidating (busca em segundo plano) para um indicador de carregamento completo.isLoading é true apenas na primeira carga, quando não há dados cacheados.isValidating é true sempre que uma requisição está em andamento, incluindo revalidações em segundo plano.isLoading é false, mas isValidating é true.Não. Chaves de objeto não são suportadas porque SWR não consegue serializá-las de forma confiável. Use strings ou arrays em vez disso. Chaves de array são serializadas internamente, então ["/api/users", id] funciona bem.
Quando múltiplos componentes chamam useSWR com a mesma chave dentro da janela dedupingInterval (padrão 2000ms), apenas uma requisição de rede é feita. Todos os hooks recebem o mesmo resultado da Promise.
SWR tratará respostas 404 e 500 como dados bem-sucedidos. O campo error permanecerá undefined. Sempre valide res.ok e lance um erro para respostas não 2xx.
Não. useSWR é um hook React que requer renderização no lado do cliente. Chamá-lo em um Server Component lançará um erro. Use fetch diretamente em Server Components e passe os dados como props.
const fetcher = ([url, token]: [string, string]) =>
fetch(url, {
headers: { Authorization: `Bearer ${token}` },
}).then((r) => r.json());
const { data } = useSWR(["/api/user", token], fetcher);Preserva os dados anteriores enquanto uma nova requisição está em andamento (por exemplo, quando a chave muda). Isso evita um flash de tela em branco entre as transições de chave, o que é especialmente útil para UIs de busca.
import useSWR, { Fetcher } from "swr";
const fetcher: Fetcher<User[], string> = (url) =>
fetch(url).then((r) => r.json());
const { data } = useSWR<User[]>("/api/users", fetcher);
// data é User[] | undefinedFetcher<Data, Key> garante que o fetcher aceite o tipo da chave como entrada e retorne Promise<Data>. Ele fornece segurança de tipo em tempo de compilação entre a chave, o fetcher e os dados retornados.
data é sempre undefined durante a carga inicial, antes do fetcher resolver. Sempre trate o estado de carregamento com isLoading ou use encadeamento opcional (data?.field) para evitar erros em tempo de execução.
Revisado por Chris St. John·Última atualização: 10 de jul. de 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥