Skip to content
Документация
Обработка ошибок

Обработка ошибок

Если ошибка возникает внутри 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 использует алгоритм экспоненциальной выдержки (opens in a new tab) для повторной попытки запроса в случае ошибки. Алгоритм позволяет приложению быстро восстанавливаться после ошибок, но не тратить ресурсы на повторные попытки слишком часто.

Вы также можете изменить это поведение с помощью опции 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 (opens in a new tab) или snackbar (opens in a new tab), или сообщить об этом куда-нибудь, например в Sentry (opens in a new tab), есть событие onError:

<SWRConfig value={{
  onError: (error, key) => {
    if (error.status !== 403 && error.status !== 404) {
      // Мы можем отправить ошибку в Sentry,
      // или показать уведомление в UI.
    }
  }
}}>
  <MyApp />
</SWRConfig>