Обработка ошибок
Если ошибка возникает внутри fetcher-а, она будет возвращена хуком как error.
const fetcher = url => fetch(url).then(r => r.json())
// ...
const { data, error } = useSWR('/api/user', fetcher)Объект error будет определен, если промис выборки будет отклонён.
Статус код и Объект ошибки
Иногда мы хотим, чтобы API возвращал объект ошибки вместе со статус кодом. Оба они полезны для клиента.
Мы можем настроить наш fetcher, чтобы он возвращал больше информации. Если статус код не 2xx,
мы считаем это ошибкой, даже если он может быть проанализирован как JSON:
const fetcher = async url => {
const res = await fetch(url)
// Если статус код не в диапазоне 200-299,
// мы все равно пытаемся его разобрать и выбросить.
if (!res.ok) {
const error = new Error('An error occurred while fetching the data.')
// Добавление дополнительной информации в объект ошибки.
error.info = await res.json()
error.status = res.status
throw error
}
return res.json()
}
// ...
const { data, error } = useSWR('/api/user', fetcher)
// error.info === {
// message: "У вас нет прав доступа к этому ресурсу.",
// documentation_url: "..."
// }
// error.status === 403Обратите внимание, что data и error могут существовать одновременно.
Таким образом, пользовательский интерфейс может отображать существующие данные, зная,
что предстоящий запрос потерпел неудачу.
Здесь у нас есть пример.
Повтор при ошибке
SWR использует алгоритм экспоненциальной выдержки для повторной попытки запроса в случае ошибки. Алгоритм позволяет приложению быстро восстанавливаться после ошибок, но не тратить ресурсы на повторные попытки слишком часто.
Вы также можете изменить это поведение с помощью опции onErrorRetry:
useSWR('/api/user', fetcher, {
onErrorRetry: (error, key, config, revalidate, { retryCount }) => {
// Никогда не повторяйте попытку при 404.
if (error.status === 404) return
// Никогда не повторяйте попытку при конкретном ключе.
if (key === '/api/user') return
// Повторить попытку до 10 раз.
if (retryCount >= 10) return
// Повторить попытку через 5 секунд.
setTimeout(() => revalidate({ retryCount }), 5000)
}
})Этот колбэк дает вам возможность повторить попытку в зависимости от различных условий. Вы также можете отключить его, установив shouldRetryOnError: false.
Также возможно предоставить его через контекст Глобальной конфигурации.
Отчёт о глобальной ошибке
Вы всегда можете реактивно получить объект error внутри компонента.
Но в случае, если вы хотите обработать ошибку глобально, чтобы уведомить UI,
чтобы показать toast или snackbar,
или сообщить об этом куда-нибудь, например в Sentry,
есть событие onError:
<SWRConfig value={{
onError: (error, key) => {
if (error.status !== 403 && error.status !== 404) {
// Мы можем отправить ошибку в Sentry,
// или показать уведомление в UI.
}
}
}}>
<MyApp />
</SWRConfig>