Skip to content
ドキュメント
はじめに

はじめに

インストール

React のプロジェクトディレクトリ内で、以下を実行します:

pnpm add swr

クイックスタート

JSON データを使用する通常の RESTful API の場合、まずネイティブの fetch をラップした fetcher 関数を作成する必要があります:

const fetcher = (...args) => fetch(...args).then(res => res.json())
💡

もし GraphQL API または Axios のようなライブラリを使いたい場合は、独自のフェッチャー関数を作ることができます。 その他の例はこちらをご覧ください。

そして、 useSWR をインポートして、任意の関数コンポーネント内で使用することができます:

import useSWR from 'swr'
 
function Profile () {
  const { data, error, isLoading } = useSWR('/api/user/123', fetcher)
 
  if (error) return <div>failed to load</div>
  if (isLoading) return <div>loading...</div>
 
  // データをレンダリングする
  return <div>hello {data.name}!</div>
}

通常、 リクエストには "loading" 、 "ready" 、 "error" の三つの状態があります。 dataerrorisLoading の値を使ってリクエストの現在の状態を判断し、 対応する UI を返すことができます。

再利用可能にする

ウェブアプリを構築する際に、 UI の多くの場所でデータを再利用する必要があるかもしれません。 SWR では再利用可能なデータフックを作るのは驚くほど簡単です:

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

そして、それをコンポーネント内で使用します:

function Avatar ({ id }) {
  const { user, isLoading, isError } = useUser(id)
 
  if (isLoading) return <Spinner />
  if (isError) return <Error />
  return <img src={user.avatar} />
}

このパターンを採用することで、リクエストを開始し、ロード状態を更新し、最終的な結果を返す、という命令的な方法でデータを取得することを忘れることができます。 代わりに、コードはより宣言的になります:コンポーネントが使用するデータを指定するだけです。

現実世界の例では、ウェブサイトにナビゲーションバーとコンテンツが表示されています。どちらも user に依存しています:

従来では、トップレベルのコンポーネントで useEffect を使用してデータを一度だけ取得し、 props を介して子コンポーネントに渡しています(現時点ではエラー状態を処理してないことに注意してください):

// ページコンポーネント
 
function Page () {
  const [user, setUser] = useState(null)
 
  // データの取得
  useEffect(() => {
    fetch('/api/user')
      .then(res => res.json())
      .then(data => setUser(data))
  }, [])
 
  // グローバルなローディング状態
  if (!user) return <Spinner/>
 
  return <div>
    <Navbar user={user} />
    <Content user={user} />
  </div>
}
 
// 子コンポーネント
 
function Navbar ({ user }) {
  return <div>
    ...
    <Avatar user={user} />
  </div>
}
 
function Content ({ user }) {
  return <h1>Welcome back, {user.name}</h1>
}
 
function Avatar ({ user }) {
  return <img src={user.avatar} alt={user.name} />
}

通常、すべてのデータをトップレベルのコンポーネントに保持し、ツリーの奥深くにあるすべてのコンポーネントに props を追加する必要があります。 ページにデータの依存関係を追加すると、コードの保守が難しくなります。

Context (opens in a new tab) を使って props を渡すことは避けられますが、動的なコンテンツの問題は残ります: ページコンテンツ内のコンポーネントは動的に変化する可能性があり、トップレベルのコンポーネントは、子コンポーネントがどのようなデータが必要かを知らないかもしれません。

SWR はその問題を完璧に解決してくれます。 先ほど作成した useUser フックを使って、コードをリファクタリングしましょう:

// ページコンポーネント
 
function Page () {
  return <div>
    <Navbar />
    <Content />
  </div>
}
 
// 子コンポーネント
 
function Navbar () {
  return <div>
    ...
    <Avatar />
  </div>
}
 
function Content () {
  const { user, isLoading } = useUser()
  if (isLoading) return <Spinner />
  return <h1>Welcome back, {user.name}</h1>
}
 
function Avatar () {
  const { user, isLoading } = useUser()
  if (isLoading) return <Spinner />
  return <img src={user.avatar} alt={user.name} />
}

Data は、そのデータを必要とするコンポーネントに結合され、すべてのコンポーネントは互いに独立しています。 すべての親コンポーネントは、データやデータの受け渡しについて何も知る必要はありません。レンダリングするだけです。 コードはずっとシンプルになり、メンテナンスも簡単になりました。

最も素晴らしいのは、 API に送られるリクエストがたった一つであることです。なぜなら、同じ SWR キーを使用した リクエストは自動的に重複排除キャッシュ共有されるからです。

また、 ユーザーのフォーカスやネットワークの再接続時 に、アプリケーションがデータを再取得できるようになりました! つまり、ユーザーのノート PC がスリープから復帰した時や、ブラウザのタブを切り替えた時に、自動的にデータが更新されるのです。