Busca en todas las páginas de la documentación
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Usa el hook useSWR con una clave y una función fetcher para obtener, cachear y revalidar datos remotos de forma declarativa en 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>Cargando...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<h1>{data.title}</h1>
{isValidating && <span>Actualizando...</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("La respuesta de red no fue correcta");
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">Error al cargar usuarios</div>;
return (
<ul>
{users?.map((user) => (
<li key={user.id}>
{user.name} - {user.email}
</li>
))}
</ul>
);
}useSWR es la clave - una cadena única (o array, o null) que identifica la solicitud y controla la caché.isLoading es true solo en la primera carga cuando aún no hay datos en caché.isValidating es true siempre que hay una solicitud en curso, incluidas las revalidaciones en segundo plano.dedupingInterval (por defecto: 2000 ms).Claves en array (fetcher con varios 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 el retorno: useSWR<Data, Error>(key, fetcher).Data.string, [string, ...args] o una función que devuelva cualquiera de los dos.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 es User[] | undefineduseSWR([url, id], ...)) está bien porque SWR serializa las claves en array internamente, pero las claves objeto no son compatibles.res.ok en tu fetcher.data es undefined durante la carga inicial. Maneja siempre el estado de carga o usa encadenamiento opcional.useSWR en un Server Component provocará un error. Los hooks de SWR son solo del lado del cliente.| Enfoque | Ventajas | Desventajas |
|---|---|---|
| useSWR | Caché automático, deduplicación, revalidación | Solo cliente, mayor tamaño del bundle |
| fetch en useEffect | Sin dependencias | Sin caché, condiciones de carrera, código repetitivo |
| React Query (TanStack) | Funciones similares, más mutaciones integradas | API más amplia |
| fetch en Server Components | Cero JS en el cliente, caché en el servidor | Sin actualizaciones en tiempo real |
De una aplicación SaaS de producción Next.js 15 / React 19 (SystemsArchitect.io).
// Ejemplo de producción: búsqueda con SWR y debounce
// Archivo: 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]);
}Lo que esto demuestra en producción:
null como clave de SWR evita la obtención por completo. Esta es la forma idiomática de obtener datos de forma condicional: cuando shouldFetch es false, la URL es null y SWR omite la solicitud.keepPreviousData: true muestra los resultados de búsqueda anteriores mientras una nueva consulta está en curso, evitando un parpadeo de pantalla en blanco entre búsquedas.dedupingInterval: 5000 evita solicitudes duplicadas para la misma clave en 5 segundos. Si el usuario escribe "react", lo borra y vuelve a escribir "react" en menos de 5 segundos, SWR devuelve el resultado en caché en lugar de llamar a la API.revalidateOnFocus: false y revalidateOnReconnect: false desactivan la revalidación automática en segundo plano. Para búsquedas, los resultados obsoletos son aceptables y volver a obtener al enfocar la pestaña sorprendería a los usuarios.useMemo en el objeto de retorno evita que los componentes consumidores se re-rendericen cuando el estado interno del hook cambia pero los valores devueltos no han cambiado.isLoading (primera carga) con isValidating (obtención en segundo plano) para un indicador de carga completo.isLoading es true solo en la primera carga cuando no hay datos en caché.isValidating es true siempre que hay una solicitud en curso, incluidas las revalidaciones en segundo plano.isLoading es false pero isValidating es true.No. Las claves objeto no son compatibles porque SWR no puede serializarlas de forma fiable. Usa cadenas o arrays en su lugar. Las claves en array se serializan internamente, así que ["/api/users", id] funciona sin problemas.
Cuando varios componentes llaman a useSWR con la misma clave dentro de la ventana dedupingInterval (2000 ms por defecto), solo se realiza una solicitud de red. Todos los hooks reciben el mismo resultado de la promesa.
SWR tratará las respuestas 404 y 500 como datos exitosos. El campo error permanecerá undefined. Valida siempre res.ok y lanza un error para respuestas que no sean 2xx.
No. useSWR es un hook de React que requiere renderizado del lado del cliente. Llamarlo en un Server Component lanzará un error. Usa fetch directamente en Server Components y pasa los datos 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 los datos anteriores mientras una nueva solicitud está en curso (p. ej., cuando cambia la clave). Esto evita un parpadeo de pantalla en blanco entre transiciones de clave, lo cual es especialmente útil para interfaces de búsqueda.
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 es User[] | undefinedFetcher<Data, Key> exige que el fetcher acepte el tipo de clave como entrada y devuelva Promise<Data>. Proporciona seguridad de tipos en tiempo de compilación entre la clave, el fetcher y los datos devueltos.
data siempre es undefined durante la carga inicial antes de que el fetcher se resuelva. Maneja siempre el estado de carga con isLoading o usa encadenamiento opcional (data?.field) para evitar errores en tiempo de ejecución.
Revisado por Chris St. John·Última actualización: 10 jul 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥