エラーハンドリング
もし 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>