Busca en todas las páginas de la documentación
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
SWR ofrece múltiples estrategias de revalidación: al enfocar la ventana, por intervalo, al reconectar y manual. Configúralas de forma global o por hook para mantener los datos actualizados sin hacer over-fetching.
"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, // Consultar cada 5 segundos
revalidateOnFocus: true, // Actualizar al enfocar la pestaña
revalidateOnReconnect: true, // Actualizar al recuperar la red
refreshWhenHidden: false, // Pausar cuando la pestaña está oculta
refreshWhenOffline: false, // Pausar cuando está sin conexión
});
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 y focus.setInterval que se dispara cada refreshInterval ms. El temporizador se pausa cuando la pestaña está oculta a menos que refreshWhenHidden sea true.online).mutate() (vinculado) o mutate(key) (global) sin argumentos.Desactivar la revalidación al enfocar de forma global:
<SWRConfig value={{ revalidateOnFocus: false }}>
{children}
</SWRConfig>Polling por intervalo condicional:
const { data } = useSWR("/api/job-status", fetcher, {
// Solo consultar mientras el trabajo está en ejecución
refreshInterval: data?.status === "running" ? 1000 : 0,
});Revalidación manual con mutate global:
import { mutate } from "swr";
// Revalidar una clave específica desde cualquier lugar
mutate("/api/users");
// Revalidar todas las claves que coincidan con un filtro
mutate(
(key) => typeof key === "string" && key.startsWith("/api/"),
undefined,
{ revalidate: true }
);Revalidar solo al montar:
const { data } = useSWR("/api/config", fetcher, {
revalidateOnFocus: false,
revalidateOnReconnect: false,
revalidateIfStale: false,
// Solo obtiene si no hay datos en caché
});SWRConfiguration y están completamente tipadas.refreshInterval acepta number o una función (latestData: Data) => number para intervalos dinámicos.const { data } = useSWR<JobStatus>("/api/job", fetcher, {
refreshInterval: (data) => (data?.complete ? 0 : 2000),
});refreshInterval: 0 desactiva el polling por intervalo (es el valor predeterminado). Establecer un intervalo muy bajo (menos de 1000 ms) puede sobrecargar tu API.refreshWhenHidden: true mantiene el polling incluso cuando el usuario está en otra pestaña. Úsalo solo cuando las actualizaciones en tiempo real importen incluso en pestañas en segundo plano.mutate() sin argumentos revalida volviendo a obtener. mutate(data) reemplaza los datos de la caché sin volver a obtener. Son operaciones muy distintas.revalidateIfStale: false, SWR no volverá a obtener al montar si ya hay datos en caché, aunque esos datos tengan horas de antigüedad.| Enfoque | Ventajas | Desventajas |
|---|---|---|
| Revalidación al enfocar | Automática, no requiere configuración | Puede dispararse con demasiada frecuencia para datos estables |
| Polling por intervalo | Simple, predecible | Ineficiente si los datos cambian poco |
| Push con WebSocket | Tiempo real, impulsado por el servidor | Requiere infraestructura WebSocket |
| Server-Sent Events (SSE) | Push ligero, basado en HTTP | Unidireccional, conexiones de navegador limitadas |
| Revalidación manual | Control total | Requiere puntos de disparo explícitos |
SWR escucha los eventos visibilitychange y focus. Cuando el usuario vuelve a la pestaña del navegador, SWR dispara una revalidación en segundo plano para todas las claves activas.
De forma predeterminada, el temporizador de polling se pausa cuando la pestaña está oculta. Establece refreshWhenHidden: true para continuar el polling en pestañas en segundo plano, pero hazlo solo cuando las actualizaciones en tiempo real importen incluso cuando la pestaña no es visible.
mutate() revalida volviendo a obtener desde el servidor.mutate(data) reemplaza los datos en caché directamente sin volver a obtener.import { mutate } from "swr";
mutate(
(key) => typeof key === "string" && key.startsWith("/api/"),
undefined,
{ revalidate: true }
);SWR no volverá a obtener al montar si ya existen datos en caché, aunque esos datos tengan horas de antigüedad. Úsalo para datos que cambian poco (p. ej., configuración de la app) combinado con desactivar la revalidación al enfocar y al reconectar.
const { data } = useSWR("/api/job-status", fetcher, {
refreshInterval: data?.status === "running" ? 1000 : 0,
});Establecer refreshInterval en 0 desactiva el polling.
Cada vez que el usuario cambia de pestaña y vuelve, SWR vuelve a obtener. Para datos estables como perfiles de usuario o configuración de la app, esto genera solicitudes innecesarias. Desactívala por hook con revalidateOnFocus: false.
SWR consultará tu API varias veces por segundo, lo que puede sobrecargar tu servidor y desperdiciar ancho de banda. Mantén intervalos razonables (mínimo 1000 ms para la mayoría de los casos de uso).
Acepta number o una función (latestData: Data) => number para intervalos dinámicos:
const { data } = useSWR<JobStatus>("/api/job", fetcher, {
refreshInterval: (data) => (data?.complete ? 0 : 2000),
});Sí. Todas las estrategias de revalidación se deduplican. Si varios componentes usan la misma clave, solo se ejecuta una solicitud de red sin importar cuántos componentes desencadenen la revalidación.
Revisado por Chris St. John·Última actualización: 7 jul 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥