Gestión De Errores
Si se lanza un error dentro del fetcher
, será devuelto como error
por el hook.
const fetcher = url => fetch(url).then(r => res.json())
// ...
const { data, error } = useSWR('/api/user', fetcher)
El objeto error
será definido si la promise de fetch es rechazada.
Código de estado y objeto de error
A veces queremos que una API devuelva un objeto de error junto con el status code. Ambos son útiles para el cliente.
Podemos personanilizar nuestro fetcher
para que devuelve más información. Si el status code no es 2xx
, lo consideramos
un error aunque se pueda analizar como JSON:
const fetcher = async url => {
const res = await fetch(url)
// Si el status code no esta en el rango 200-299,
// seguimos intentando analizarlo y lanzarlo.
if (!res.ok) {
const error = new Error('An error occurred while fetching the data.')
// Adjunta información extra al objeto de error.
error.info = await res.json()
error.status = res.status
throw error
}
return res.json()
}
// ...
const { data, error } = useSWR('/api/user', fetcher)
// error.info === {
// message: "You are not authorized to access this resource.",
// documentation_url: "..."
// }
// error.status === 403
Tenga en cuenta que data
y error
pueden existir al mismo tiempo. Por lo tanto la UI puede mostrar
data existente, mientras se sabe que la próxima solicitud ha fallado.
Aquí tenemos un ejemplo.
Reintento de error
SWR utiliza el exponential backoff algorithm (opens in a new tab) para reintentar la solicitud en el error. El algoritmo permite que la aplicación se recupere de los errores rápidamente, pero si malgastar recursos reintentando con demasiada frecuencia.
También podemos anular este comportamiento mediante la opción onErrorRetry:
useSWR('/api/user', fetcher, {
onErrorRetry: (error, key, config, revalidate, { retryCount }) => {
// Never retry on 404.
if (error.status === 404) return
// Never retry for a specific key.
if (key === '/api/user') return
// Only retry up to 10 times.
if (retryCount >= 10) return
// Retry after 5 seconds.
setTimeout(() => revalidate({ retryCount }), 5000)
}
})
Este callback le da flexibilidad de reintentar basado en varias condiciones. También puede desactivar estableciendo shouldRetryOnError: false
.
También es posible propocionar a través del Global Configuration context.
Informe global de errores
Siempre puedes obtener el objeto de error
dentro del componente de forma reactiva. Pero en caso de que quieras manejar el error de forma global,
para notificar a la UI que muestre un toast (opens in a new tab) o un snackbar (opens in a new tab), o reportarlo
en algún lugar como Sentry (opens in a new tab), hay un evento onError
:
<SWRConfig value={{
onError: (error, key) => {
if (error.status !== 403 && error.status !== 404) {
// Podemos enviar el error a Sentry
// o mostrarlo una notificación UI.
}
}
}}>
<MyApp />
</SWRConfig>