📖

React Query-データ取得編

2022/08/01に公開

TanStack | High Quality Open-Source Software for Web Developers

React Query について公式ドキュメントを読みながら自分に必要なものをまとめたメモを記事化したもので以下の 4 つの記事で構成されています。記事ができたものから順次リンク化していきます。

データの取得 - useQuery

Queries | TanStack Query Docs

useQuery を使う

const { isLoading, isError, data, error } = useQuery(['users'], getUsers)

if (isLoading) {
  return <span>Now Loading...</span>
}
if (isError) {
  if (error instanceof Error) {
    return <span>{error.message}</span>
  }
}
return (
  <ul>
    {data.map(user => (<li key={user.id}>{user.name}</li>))}
  </ul>
)
  • 引数
    • 第一引数にキャッシュキーとなる配列を指定する
    • 第二引数にデータ取得関数を指定する
    • 第三引数にオプションを指定したオブジェクトを渡せる
      • staleTime 等をクエリ単位で調整したい場合はここで行う
  • 戻り値
    • 上記の例で分割代入しているように実際に返ってくるものはオブジェクト
    • isLoading はキャッシュも含めてデータがなければ true となる
    • isFetching もあり、こちらはデータ取得中であれば true となる
      • データの再取得中にローディングアイコンを表示したい時などに使う
    • data に取得したデータが入る
    • エラー発生時に isError が true となり error にエラー情報が入る
      • 上記の例だと error の型が unknown となるので instaceof を使う必要がある
      • 以下のように useQuery の Generics を指定する方法でも回避できる
useQuery<ResponseType, ErrorType>(['users'], getUsers)

更新ボタンなどを作りたい時は refetch が使える

const { refetch } = useQuery(['users'], getUsers)
return (
  <button onClick={refetch}>Update</button>
)

キャッシュキー - Query Keys

Query Keys | TanStack Query Docs
キャッシュキーの配列は文字列だけでなく数値やオブジェクトも指定できる

useQuery(['users', 5, { role: 'owner' }], ...)
  • キャッシュを無効化する際などにこの配列の順番が重要となる
    • 無効化対象を指定する時のキー配列は前方一致で指定するようになっている
    • ['users'] を指定すると上記の例のキャッシュも削除対象となる

データ取得関数 - Query Functions

Query Functions | TanStack Query Docs

  • useQuery の第二引数に指定する関数のことで Promise を返す必要がある
  • この関数内で例外が投げられると error に格納され isError が true となる

データ取得関数に引数を渡す方法は無名関数を使う方法と QueryFunctionContext を受け取る関数を作る方法とがある。

無名関数を使う。

useQuery(['users', userId], () => getUserById(userId))

// 後述する QueryFunctionContext を受け取っても良い
useQuery(['users', userId], ({ queryKey }) => getUserId(queryKey[1]))

QueryFunctionContext を使った関数を作る。

import { QueryFunctionContext } from '@tanstack/react-query'

const getUserId = (context: QueryFunctionContext) => {
  const userId = context.queryKey[1]
}

上記の QueryFunctionContext を使う関数は useQuery に指定するキャッシュキーの順番に暗黙的に依存し、実際に useQuery で使う所とは分離されているので修正漏れが起きやすくなってしまう可能性が高い。基本的には無名関数を使ったカスタムフックに切り出すのがおすすめ。

axios 等を使わずに fetch 関数を使う場合はネットワークエラー以外は例外を投げない仕様なので以下のような対応が必要になる。(ok が true になるのはステータスコードが 200 番台の時)

const response = await fetch('/users')
if (!response.ok) {
  throw new Error(response.statusText)
}
return response.json()

その他

詳細はまだ調べていないけど使用する可能性の高い機能のメモ

Infinite Queries | TanStack Query Docs
無限スクロールなどに使えるデータを順次追加していく機能

Parallel Queries | TanStack Query Docs
並列に同時実行できる機能

Discussion