Skip to content
ドキュメント
エラーハンドリング

エラーハンドリング

もし fetcher 内でエラーが投げられた場合、フックは error として返します。

const fetcher = url => fetch(url).then(r => r.json())
 
// ...
const { data, error } = useSWR('/api/user', fetcher)

フェッチの promise がリジェクトされた場合、 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: "You are not authorized to access this resource.",
//   documentation_url: "..."
// }
// error.status === 403
💡

データエラー は同時に存在することに注意してください。そのため、 UI は次のリクエストが失敗したことを知りながら、 既存のデータを表示することができます。

ここではその例を紹介しています。

エラー時の再試行

SWR は exponential backoff アルゴリズム (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 オブジェクトをいつでもリアクティブに取得することができます。 ただし、エラーをグローバルに処理したり、 トースト (opens in a new tab)スナックバー (opens in a new tab) を表示するように UI に通知したり、 Sentry (opens in a new tab) などの場所で報告する場合は、 onError イベントがあります:

<SWRConfig value={{
  onError: (error, key) => {
    if (error.status !== 403 && error.status !== 404) {
      // エラーをSentryに送信するか、
      // 通知UIを表示することができます。
    }
  }
}}>
  <MyApp />
</SWRConfig>