LoginSignup
13
8

More than 1 year has passed since last update.

ReactQueryチートシート

Posted at

パッケージインストール

$ npm i react-query

セットアップ

app.tsx
import React from 'react'
import { QueryClient, QueryClientProvider } from 'react-query'

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      suspense: true,
    },
  },
})

const App = () => {
  return (
    <QueryClientProvider client={queryClient}>
      <SomethingComponent />
    </QueryClientProvider>
  )
}
export default MyApp

カスタムフックの作成

useQuery(データ取得用)

useFetchSomethingQuery
import { useQuery } from 'react-query'

type Something = {
  name: string
  email: string
}

type SomethingResponse = { data: Something[] }

// fetcher関数定義
const fetchGet = <T>(url: string): Promise<T> => {
  const options = {
    method: 'GET'
  }
  return fetch(url, options)
    .then((res) => {
      return res.json()
    })
    .catch((err) => {
      throw new Error(err)
    })
}

export const useFetchSomethingQuery = () => {
  const url = 'https://api.something.com/something'
  
  // useQueryの第一引数にはユニークなキーを設定
  return useQuery('fetchSomething', () =>
    fetchGet<SomethingResponse>(url)
  )
}

useMutation(データ更新用)

import { useMutation, useQueryClient } from 'react-query'

type Something = {
  name: string
  email: string
}

type SomethingResponse = { data: { message: 'Success' } }

// fetcher関数定義
const fetchPost = <T>(url: string, data: Something): Promise<T> => {
  const options = {
    method: 'POST',
    body: JSON.stringify(data),
  }
  return fetch(url, options)
    .then((res) => {
      return res.json()
    })
    .catch((err) => {
      throw new Error(err)
    })
}

export const usePostSomethingMutation = () => {
  const queryClient = useQueryClient()
  const url = 'https://api.something.com/something'

  return useMutation((data: Something) => fetchPost<SomethingResponse>(url, data),
    {
      /*
        成功時にuseQueryのkeyを設定することで、キャッシュを破棄して自動で再フェッチしてくれる
        POSTした値を再フェッチしてリアルタイムで画面に描画したい時などに便利
      */
      onSuccess: () => {
        queryClient.invalidateQueries('fetchSomething')
      },
    }
  )
}

コンポーネントで使う

GET

components/SomethingComponent
import React from 'react'
import useFetchSomethingQuery from '../api/useFetchSomethingQuery'

export const SomethingComponent = () => {

  const { data, isLoading } = useFetchSomethingQuery()
  const something = data?.data
 
  if (isLoading) return 'Loading...'
  
  return (
    <div>
      <h1>{something.name}</h1>
      <p>{something.email}</p>
    </div>
  )
}

POST

components/SomethingComponent
import React from 'react'
import usePostSomethingMutation from '../api/usePostSomethingMutation'

export const SomethingComponent = () => {

  const postMutation = usePostSomethingMutation()
  const data = {
    name: 'some',
    email: 'thing@.com'
  }

  const handleSubmit((data) => {
    // 成功時に何かしらの処理をしたい場合は第二引数に関数を渡す
    postMutation.mutate(
      data,
      { onSuccess: () => something() }
    )
  })
 
  if (postMutation.isLoading) return 'Loading...'
  
  return (
    <div>
      <button onClick={() => handleSubmit(data)}>
        POST!
      </button>
    </div>
  )
}

Tips

Suspenseを使う

  • defaultOptionsqueries.suspenseをtrueに設定する必要がある
  • 親コンポーネントで非同期処理をキャッチすることができる
export const SomethingContainer = () => {

  return (
    <div>
      <Suspense fallback={'Loading...'}>
        <SomethingComponent />
      </Suspense>
    </div>
  )
}

再フェッチするトリガーを指定したい

  • useQueryの第一引数は配列にすることができる
  • 以下ではparamsの値が変化したときに再フェッチを行う
export const useFetchSomethingQuery = () => {
  const params = useParams()
  const url = 'https://api.something.com/something'
  
  return useQuery(['fetchSomething', params], () =>
    fetchGet<SomethingResponse>(url)
  )
}

参考資料

13
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
8