🦕

React Queryに入門してみる

2022/09/03に公開

Reduxという状態管理手法がよく注目されがちだけど、もっと簡潔に、かつユースケースに即した管理手法はないか、と考えたときにTwitterで見かけたReact Query。
APIで渡ってきたデータのキャッシュとして使えそうなので、使い方を学んでいきます。

create react appする。
友人からバッケージマネージャーにpnpm、ビルドツールにViteをお薦めされたので一緒に試してみる。

pnpm create vite@latest

いい感じに起動できた。
次にグローバルに状態管理できるようにするために、QueryClientProviderコンポーネントをAppコンポーネントにラップする。
QueryClientをインスタンス化して、Propsに渡す。

/src/App.tsx

import reactLogo from './assets/react.svg'
import './App.css'
import { QueryClient, QueryClientProvider } from 'react-query'
import { User } from './components/users';

function App() {
  const queryClient = new QueryClient();

  return (
    <QueryClientProvider client={queryClient}>
      <div className="App">
        <div>
          <a href="https://vitejs.dev" target="_blank">
            <img src="/vite.svg" className="logo" alt="Vite logo" />
          </a>
          <a href="https://reactjs.org" target="_blank">
            <img src={reactLogo} className="logo react" alt="React logo" />
          </a>
        </div>
        <h1>Vite + React</h1>
      </div>
      <User />
    </QueryClientProvider>
  )
}

次にグローバルで呼びたいオブジェクトをフェッチして、グローバルに保持できるようにする。
hooksフォルダにuseQueryUsersを作成
APIを叩いて返ってきたJSONオブジェクトをqueryKey: usersとして保存。

戻り値にuseQueryメソッドを記述して引数にオブジェクトで以下3つのプロパティを指定。
queryKeyにはオブジェクトの変数となる名前を(ユニークである必要がある)、
queryFnにはオブジェクトを取得する関数名を、
onErrorにはエラーハンドリングをそれぞれ記載

/src/hooks/useQueryUser.tsx

import { useQuery } from "react-query";

export const useQueryUser = () => {
  const fetchUsers = async () => {
    const res = await fetch('https://jsonplaceholder.typicode.com/users');
    return res.json();
  };
  
  return useQuery<any[], Error>({
    queryKey: ['users'],
    queryFn: fetchUsers,
    onError: (err: any) => {
      if (err.response.status === 401 || err.status === 403) {
      }
    }
  })
};

使用したいコンポーネントでhooksの呼び出しをする。

/src/components/User.tsx

import { useQueryUser } from "../hooks/useQueryUsers";

export const User = () => {
  const { data: users } = useQueryUser();

  return (
    <div>
        <h2>ユーザー一覧</h2>
        <div>
          {users?.map((user: any, index: number) => (
             <div key={index}>{user.name}</div>
          ))}
        </div>
      </div>
  );
};

画面としてはこんな感じ

これでOK!
一度呼び出し後は、キャッシュとして残るため、レンダリングするたびにAPIを叩くということはなくなるのでパフォーマンスの向上につながる。

Discussion