错误处理
如果在 fetcher
中抛出错误,hook 会将其作为 error
返回。
const fetcher = url => fetch(url).then(r => r.json())
// ...
const { data, error } = useSWR('/api/user', fetcher)
如果 fetch 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
💡
注意:data
和 error
可以同时存在。所以 UI 可以在知道即将到来的请求失败时显示现有数据。
这里有一个示例。
错误重试
在出现错误时 SWR 使用指数退避算法 (opens in a new tab)重发请求。该算法允许应用从错误中快速恢复,而不会浪费资源频繁地重试。
你还可以通过 onErrorRetry 选项覆盖该行为:
useSWR('/api/user', fetcher, {
onErrorRetry: (error, key, config, revalidate, { retryCount }) => {
// 404 时不重试。
if (error.status === 404) return
// 特定的 key 时不重试。
if (key === '/api/user') return
// 最多重试 10 次。
if (retryCount >= 10) return
// 5秒后重试。
setTimeout(() => revalidate({ retryCount: retryCount }), 5000)
}
})
这个回调让你可以灵活的根据各种条件重试。你也可以通过设置 shouldRetryOnError: false
来禁用它。
也可以通过全局配置 context 来提供它。
全局错误报告
你总是可以响应性的在组件内部得到 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>