Busque em todas as páginas da documentação
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
O SWR oferece múltiplas estratégias de revalidação: ao focar na janela, por intervalo, ao reconectar e manualmente. Configure-as globalmente ou por hook para manter os dados frescos sem excesso de requisições.
"use client";
import useSWR from "swr";
const fetcher = (url: string) => fetch(url).then((r) => r.json());
function StockPrice({ symbol }: { symbol: string }) {
const { data } = useSWR(`/api/stocks/${symbol}`, fetcher, {
refreshInterval: 5000, // Poll every 5 seconds
revalidateOnFocus: true, // Refresh on tab focus
revalidateOnReconnect: true, // Refresh on network recovery
refreshWhenHidden: false, // Pause when tab is hidden
refreshWhenOffline: false, // Pause when offline
});
return <span>${data?.price}</span>;
}"use client";
import useSWR, { useSWRConfig } from "swr";
import { useState } from "react";
interface Notification {
id: string;
message: string;
read: boolean;
}
const fetcher = (url: string): Promise<Notification[]> =>
fetch(url).then((r) => r.json());
export default function NotificationCenter() {
const { data: notifications, mutate } = useSWR<Notification[]>(
"/api/notifications",
fetcher,
{
refreshInterval: 30000, // Auto-refresh every 30s
revalidateOnFocus: true, // Check on tab return
}
);
const handleManualRefresh = () => {
mutate(); // Trigger manual revalidation
};
const handleMarkAllRead = async () => {
await fetch("/api/notifications/mark-read", { method: "POST" });
mutate(); // Revalidate after mutation
};
return (
<div>
<div className="flex justify-between">
<h2>Notifications ({notifications?.filter((n) => !n.read).length ?? 0} unread)</h2>
<button onClick={handleManualRefresh}>Refresh</button>
</div>
<ul>
{notifications?.map((n) => (
<li key={n.id} className={n.read ? "opacity-50" : ""}>
{n.message}
</li>
))}
</ul>
<button onClick={handleMarkAllRead}>Mark all as read</button>
</div>
);
}visibilitychange e focus.setInterval que dispara a cada refreshInterval ms. O timer pausa quando a aba está oculta, a menos que refreshWhenHidden seja true.online).mutate() (local) ou mutate(key) (global) sem argumentos.Desabilitar revalidação ao focar globalmente:
<SWRConfig value={{ revalidateOnFocus: false }}>
{children}
</SWRConfig>Polling por intervalo condicional:
const { data } = useSWR("/api/job-status", fetcher, {
// Only poll while the job is running
refreshInterval: data?.status === "running" ? 1000 : 0,
});Revalidação manual com mutate global:
import { mutate } from "swr";
// Revalidate a specific key from anywhere
mutate("/api/users");
// Revalidate all keys matching a filter
mutate(
(key) => typeof key === "string" && key.startsWith("/api/"),
undefined,
{ revalidate: true }
);Revalidar apenas ao montar:
const { data } = useSWR("/api/config", fetcher, {
revalidateOnFocus: false,
revalidateOnReconnect: false,
revalidateIfStale: false,
// Only fetches if no cached data exists
});SWRConfiguration e são totalmente tipadas.refreshInterval aceita number ou uma função (latestData: Data) => number para intervalos dinâmicos.const { data } = useSWR<JobStatus>("/api/job", fetcher, {
refreshInterval: (data) => (data?.complete ? 0 : 2000),
});refreshInterval: 0 desabilita o polling por intervalo (é o padrão). Definir um intervalo muito baixo (abaixo de 1000ms) pode sobrecarregar sua API.refreshWhenHidden: true mantém o polling mesmo quando o usuário está em outra aba. Use apenas quando atualizações em tempo real são importantes, mesmo em abas em segundo plano.mutate() sem argumentos revalida buscando novamente do servidor. mutate(data) substitui os dados do cache diretamente, sem buscar novamente. Estas são operações muito diferentes.revalidateIfStale: false, o SWR não buscará novamente ao montar se houver dados em cache, mesmo que esses dados tenham horas de idade.| Abordagem | Prós | Contras |
|---|---|---|
| Revalidação ao Focar | Automática, sem necessidade de configuração | Pode disparar com muita frequência para dados estáveis |
| Polling por Intervalo | Simples, previsível | Desperdício se os dados raramente mudam |
| Push WebSocket | Tempo real, controlado pelo servidor | Requer infraestrutura WebSocket |
| Server-Sent Events (SSE) | Push leve, baseado em HTTP | Unidirecional, conexões limitadas no navegador |
| Revalidação Manual | Controle total | Requer pontos de gatilho explícitos |
O SWR escuta os eventos visibilitychange e focus. Quando o usuário retorna para a aba do navegador, o SWR dispara uma revalidação em segundo plano para todas as chaves ativas.
Por padrão, o timer de polling pausa quando a aba está oculta. Defina refreshWhenHidden: true para continuar o polling em abas em segundo plano, mas faça isso apenas quando atualizações em tempo real forem importantes mesmo quando a aba não estiver visível.
mutate() revalida buscando novamente do servidor.mutate(data) substitui os dados em cache diretamente sem buscar novamente.import { mutate } from "swr";
mutate(
(key) => typeof key === "string" && key.startsWith("/api/"),
undefined,
{ revalidate: true }
);O SWR não buscará novamente ao montar se já existirem dados em cache, mesmo que esses dados tenham horas de idade. Use isso para dados que raramente mudam (por exemplo, configurações do aplicativo) combinado com a desabilitação da revalidação ao focar e ao reconectar.
const { data } = useSWR("/api/job-status", fetcher, {
refreshInterval: data?.status === "running" ? 1000 : 0,
});Definir refreshInterval para 0 desabilita o polling.
Toda vez que o usuário muda de aba e retorna, o SWR busca novamente. Para dados estáveis como perfis de usuário ou configurações do aplicativo, isso cria requisições desnecessárias. Desabilite-o por hook com revalidateOnFocus: false.
O SWR consultará sua API várias vezes por segundo, o que pode sobrecarregar seu servidor e desperdiçar largura de banda. Mantenha os intervalos razoáveis (mínimo de 1000ms para a maioria dos casos de uso).
Ele aceita number ou uma função (latestData: Data) => number para intervalos dinâmicos:
const { data } = useSWR<JobStatus>("/api/job", fetcher, {
refreshInterval: (data) => (data?.complete ? 0 : 2000),
});Sim. Todas as estratégias de revalidação são deduplicadas. Se múltiplos componentes usarem a mesma chave, apenas uma requisição de rede será executada, independentemente de quantos componentes dispararem a revalidação.
Revisado por Chris St. John·Última atualização: 7 de jul. de 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥