MeWrite Docs

useSWR: Error fetching data

SWRでデータフェッチに失敗した場合のエラーハンドリング

概要

SWRでデータフェッチ中にエラーが発生した場合の対処法です。ネットワークエラー、APIエラー、設定ミスなど様々な原因があります。

エラーメッセージ

Error: An error occurred while fetching the data.
SWRError: Failed to fetch
TypeError: Failed to fetch

解決策

1. 基本的なエラーハンドリング

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import useSWR from 'swr'

const fetcher = async (url: string) => {
  const res = await fetch(url)

  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()
}

function Profile() {
  const { data, error, isLoading } = useSWR('/api/user', fetcher)

  if (error) return <div>Failed to load: {error.message}</div>
  if (isLoading) return <div>Loading...</div>

  return <div>Hello {data.name}!</div>
}

2. グローバルエラーハンドリング

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import { SWRConfig } from 'swr'

function App() {
  return (
    <SWRConfig
      value={{
        fetcher: (url) => fetch(url).then((res) => res.json()),
        onError: (error, key) => {
          if (error.status !== 403 && error.status !== 404) {
            // エラーログを送信
            console.error(`SWR Error for ${key}:`, error)
          }
        },
        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)
        },
      }}
    >
      <YourApp />
    </SWRConfig>
  )
}

3. リトライ設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const { data, error } = useSWR('/api/data', fetcher, {
  // エラー時の再試行設定
  errorRetryCount: 3,
  errorRetryInterval: 5000,

  // フォーカス時の再検証を無効化
  revalidateOnFocus: false,

  // 再接続時の再検証
  revalidateOnReconnect: true,
})

4. Axiosとの組み合わせ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import axios from 'axios'
import useSWR from 'swr'

const fetcher = (url: string) => axios.get(url).then((res) => res.data)

function useUser(id: string) {
  const { data, error, isLoading } = useSWR(`/api/user/${id}`, fetcher)

  return {
    user: data,
    isLoading,
    isError: error,
  }
}

5. 条件付きフェッチ

1
2
3
4
5
// userがnullの場合はフェッチしない
const { data } = useSWR(user ? `/api/user/${user.id}` : null, fetcher)

// shouldFetchがfalseの場合はフェッチしない
const { data } = useSWR(shouldFetch ? '/api/data' : null, fetcher)

6. エラー境界との組み合わせ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import { ErrorBoundary } from 'react-error-boundary'

function ErrorFallback({ error, resetErrorBoundary }) {
  return (
    <div>
      <p>Something went wrong:</p>
      <pre>{error.message}</pre>
      <button onClick={resetErrorBoundary}>Try again</button>
    </div>
  )
}

function App() {
  return (
    <ErrorBoundary FallbackComponent={ErrorFallback}>
      <Profile />
    </ErrorBoundary>
  )
}

7. ミューテーション時のエラー

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import useSWRMutation from 'swr/mutation'

async function updateUser(url: string, { arg }: { arg: { name: string } }) {
  const res = await fetch(url, {
    method: 'POST',
    body: JSON.stringify(arg),
  })

  if (!res.ok) {
    throw new Error('Failed to update user')
  }

  return res.json()
}

function Profile() {
  const { trigger, isMutating, error } = useSWRMutation('/api/user', updateUser)

  return (
    <button
      disabled={isMutating}
      onClick={() => trigger({ name: 'New Name' })}
    >
      Update
    </button>
  )
}

関連エラー

関連エラー

React の他のエラー

最終更新: 2025-12-19