[日本語訳]SWR ドキュメンテーション エラーハンドリング


追記: 2021年6月8日

SWR公式日本語訳ページが追加されたので、そちらをご覧ください

このページは Error Handling – SWRの日本語訳です
SWR日本語訳全体についてはSWR 日本語訳をご覧ください

エラーハンドリング

fetcher 内でエラーがスローされた場合、フックによってerrorとして返されます。


const fetcher = url => fetch(url).then(r => r.json())

// ...
const { data, error } = useSWR('/api/user', fetcher)

fetch promise が reject された場合に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

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

ここに例があります

エラーでの再試行

SWRは、指数バックオフアルゴリズム(exponential backoff algorithm)を使用して、エラー時に要求を再試行します。 このアルゴリズムにより、アプリはエラーからすばやく回復できますが、リソースを無駄に再試行することはありません。

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: retryCount + 1 }), 5000)
  }
})

このコールバックにより、さまざまな条件に基づいて再試行できる柔軟性が得られます。 shouldRetryOnError:false を設定して無効にすることもできます。

これらは グローバル設定 Context を介して設定することもできます。

グローバルエラーレポート

コンポーネント内の error オブジェクトはいつでもリアクティブに取得できます。 ただし、エラーをグローバルで処理する場合、toastsnackbar を表示するようにUIに通知する場合、またはSentryなどの場所で報告する場合は、onErrorイベントがあります。


<SWRConfig value={{
  onError: (error, key) => {
    if (error.status !== 403 && error.status !== 404) {
      // Sentry にエラーを送信します
      // または、通知UIを表示します
    }
  }
}}>
  <MyApp />
</SWRConfig>