Fetching condicional y dependiente
Receta
Pasa null o un valor falsy como clave para evitar que SWR haga fetch. Úsalo para esperar dependencias, restringir solicitudes tras la autenticación o encadenar fetches secuenciales.
"use client";
import useSWR from "swr";
function UserProjects({ userId }: { userId: string | null }) {
// No hará fetch hasta que userId esté disponible
const { data } = useSWR(userId ? `/api/users/${userId}/projects` : null, fetcher);
return <div>{data?.length ?? 0} proyectos</div>;
}Ejemplo funcional
"use client";
import useSWR from "swr";
const fetcher = (url: string) => fetch(url).then((r) => r.json());
interface User {
id: string;
name: string;
teamId: string;
}
interface Team {
id: string;
name: string;
members: string[];
}
export default function UserTeamInfo({ userId }: { userId: string }) {
// Paso 1: Obtener usuario
const { data: user, isLoading: userLoading } = useSWR<User>(
`/api/users/${userId}`,
fetcher
);
// Paso 2: Obtener equipo solo después de que cargue el usuario (fetching dependiente)
const { data: team, isLoading: teamLoading } = useSWR<Team>(
user ? `/api/teams/${user.teamId}` : null,
fetcher
);
if (userLoading) return <p>Cargando usuario...</p>;
if (teamLoading) return <p>Cargando equipo de {user?.name}...</p>;
return (
<div>
<p>{user?.name} pertenece al equipo {team?.name}</p>
<p>El equipo tiene {team?.members.length} miembros</p>
</div>
);
}Profundización
Cómo funciona
- Cuando la clave es
null,undefined,falseo"", SWR omite el fetch por completo y devuelve{ data: undefined, error: undefined, isLoading: false }. - Esta es la forma idiomática de implementar fetching dependiente (cascada): la clave de la segunda solicitud se deriva de los datos de la primera.
- Una vez que la clave pasa a ser truthy, SWR dispara el fetch de inmediato.
- También se admite la forma de función clave
() => condition ? key : null, que se evalúa en cada render.
Variaciones
Clave como función:
const { data } = useSWR(
() => (isLoggedIn ? `/api/profile` : null),
fetcher
);Múltiples dependencias:
const { data: user } = useSWR("/api/me", fetcher);
const { data: org } = useSWR(user ? `/api/orgs/${user.orgId}` : null, fetcher);
const { data: billing } = useSWR(
user && org ? `/api/orgs/${org.id}/billing` : null,
fetcher
);Condicional con clave de array:
const { data } = useSWR(
token ? ["/api/data", token] : null,
([url, token]) =>
fetch(url, { headers: { Authorization: `Bearer ${token}` } }).then((r) => r.json())
);Lanzar error en la función clave para pausar:
// Lanzar un error dentro de la función clave también pausa el fetch
const { data } = useSWR(
() => `/api/users/${userId ?? throwUndefined()}`,
fetcher
);
function throwUndefined(): never {
throw new Error("no está listo");
}Notas de TypeScript
- Al usar claves condicionales, el tipo de
datasigue siendoData | undefinedporque el fetch puede no haberse ejecutado aún. - Si la clave es
null, TypeScript infiere el tipo de clave comonull. Usa un tipo unión o genérico para mantenerlo limpio.
const { data } = useSWR<Team>(
user ? `/api/teams/${user.teamId}` : null,
fetcher
);
// data: Team | undefinedErrores comunes
- El fetching dependiente crea una cascada. Cada solicitud encadenada debe esperar a la anterior. Mantén las cadenas cortas para evitar cargas de página lentas.
- Cuando la clave pasa de
nulla un valor real,isLoadingse vuelvetruedurante esa transición. Planifica tu UI de carga en consecuencia. - Si usas una función clave que lanza un error, SWR lo trata igual que una clave
null. Sin embargo, los errores lanzados en la función clave se capturan silenciosamente y no aparecen enerror. - No confundas el fetching condicional (clave null) con el manejo de errores. Una clave null significa «no hacer fetch», no «el fetch falló».
Alternativas
| Enfoque | Ventajas | Desventajas |
|---|---|---|
| Clave null (SWR) | Declarativo, se dispara automáticamente al cambiar | Crea cascada para fetches dependientes |
| Opción enabled (React Query) | Bandera booleana explícita | No disponible de forma nativa en SWR |
| Guardia con useEffect | Patrón imperativo familiar | Pierde los beneficios de caché y deduplicación de SWR |
| Join en el servidor | Una sola solicitud, sin cascada | Requiere cambios en la API, menos flexible |
FAQs
¿Qué valores puedo pasar como clave para evitar que SWR haga fetch?
SWR omite el fetch cuando la clave es null, undefined, false o una cadena vacía "". Cualquiera de estos valores falsy evitará la solicitud.
¿Qué devuelve useSWR cuando la clave es null?
Devuelve { data: undefined, error: undefined, isLoading: false }. No se hace ningún fetch — isLoading es false porque no hay nada que cargar.
¿Cómo encadeno fetches secuenciales (dependientes) con SWR?
Deriva la clave de la segunda solicitud a partir de los datos de la primera:
const { data: user } = useSWR("/api/me", fetcher);
const { data: team } = useSWR(
user ? `/api/teams/${user.teamId}` : null,
fetcher
);El fetch del equipo se ejecuta solo después de que user esté disponible.
¿Puedo pasar una función como clave a useSWR para fetching condicional?
Sí. SWR evalúa una función clave en cada render:
const { data } = useSWR(
() => (isLoggedIn ? `/api/profile` : null),
fetcher
);Trampa: ¿El fetching dependiente crea una cascada y cómo debo manejarlo?
Sí. Cada solicitud encadenada espera a la anterior. Mantén las cadenas de dependencias cortas (2-3 como máximo) para evitar cargas de página lentas. Si es posible, combina los datos en un único endpoint de API en el servidor.
¿Qué ocurre cuando una función clave lanza un error?
SWR trata un error lanzado dentro de la función clave igual que una clave null: pausa el fetch. Sin embargo, el error se captura silenciosamente y no aparece en el valor de retorno error.
¿Cómo uso fetching condicional con claves de array?
const { data } = useSWR(
token ? ["/api/data", token] : null,
([url, token]) =>
fetch(url, {
headers: { Authorization: `Bearer ${token}` },
}).then((r) => r.json())
);Trampa: ¿Una clave null es lo mismo que un fetch fallido?
No. Una clave null significa «no hacer fetch». No es un estado de error. error permanece undefined e isLoading es false. No confundas el fetching condicional con el manejo de errores.
¿Cómo maneja TypeScript el tipo de data cuando la clave puede ser null?
El tipo de data sigue siendo Data | undefined porque el fetch puede no haberse ejecutado aún. Usa un tipo unión o genérico para mantenerlo limpio:
const { data } = useSWR<Team>(
user ? `/api/teams/${user.teamId}` : null,
fetcher
);
// data: Team | undefinedCuando la clave pasa de null a un valor real, ¿qué ocurre con isLoading?
isLoading se vuelve true durante esa transición mientras SWR obtiene datos para la clave recién truthy. Planifica tu UI de carga para tener en cuenta este cambio de estado.
¿Cómo se compara el fetching condicional de SWR con la opción enabled de React Query?
SWR usa claves null/falsy para evitar el fetch, mientras que React Query tiene una opción booleana explícita enabled. El enfoque de SWR es declarativo y guiado por la clave; el de React Query es más explícito pero no está disponible de forma nativa en SWR.