Manipulação de Erros
Se um erro é lançado dentro de fetcher
, ele será retornado como error
pelo hook.
const fetcher = url => fetch(url).then(r => r.json())
// ...
const { data, error } = useSWR('/api/user', fetcher)
O objeto error
será definido se a fetch promise for rejeitada.
Código de Status e Objeto de Erro
As vezes queremos uma API para retornar um objeto de erro junto ao código de status. Ambos são úteis para o cliente.
Nós podemos customizar nossa função fetcher
para retornar mais informações. Se o código de status não for 2xx
,
consideramos que é um erro mesmo se ele puder ser lido como JSON:
const fetcher = async url => {
const res = await fetch(url)
// Se o código de status não estiver no raio 200-299,
// nós ainda tentamos ler o JSON e retornar o objeto de erro
if (!res.ok) {
const error = new Error('An error occurred while fetching the data.')
// Adicionar informação extra ao objeto de erro.
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
Note que data
e error
podem existir ao mesmo tempo. Então a UI pode mostrar os dados existentes,
enquanto sabe que o próximo pedido falhou.
Aqui nós temos um exemplo.
Retentativas
SWR usa o algoritmo de retentativa exponencial (em inglês) (opens in a new tab) para tentar novamente a requisição em caso de erro. O algoritmo permite a aplicação se recuperar rapidamente de erros, mas não gasta muitos recursos tentando novamente muito frequentemente.
Você também pode sobrescrever este comportamento através da opção onErrorRetry:
useSWR('/api/user', fetcher, {
onErrorRetry: (error, key, config, revalidate, { retryCount }) => {
// Nunca tentar ao 404.
if (error.status === 404) return
// Nunca tentar para uma chave específica
if (key === '/api/user') return
// Tentar até 10 vezes.
if (retryCount >= 10) return
// Tentar novamente depois de 5 segundos
setTimeout(() => revalidate({ retryCount }), 5000)
}
})
Esse callback dá a você a flexibilidade de tentar novamente baseado em várias condições. Você também pode desativá-lo definindo shouldRetryOnError: false
.
Também é possível provê-lo via contexto de Configuração Global.
Relatório de Erros Globais
Você pode sempre obter o objeto de erro dentro do componente reativamente.
Mas, no caso de você querer lidar com o erro globalmente, para notificar a UI para mostrar um toast (opens in a new tab) ou snackbar (opens in a new tab), ou reportá-lo em algum lugar como Sentry (opens in a new tab),
há um evento chamado onError
:
<SWRConfig value={{
onError: (error, key) => {
if (error.status !== 403 && error.status !== 404) {
// Nós podemos enviar o erro para Sentry,
// ou mostrar uma notificação na interface.
}
}
}}>
<MyApp />
</SWRConfig>