2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

React Queryを利用したデータ取得・更新のサンプル

Posted at

インストール

npm install react-query

まずQueryClientとQueryClientProviderを設定

App.tsx

import { QueryClient, QueryClientProvider } from 'react-query'

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      retry: false,
      refetchOnWindowFocus: false,
    },
  },
})

const App = () => {
  return (
    <QueryClientProvider client={queryClient}>
     ...
    </QueryClientProvider>
  )
}

ここでdefaultOptionを設定すると全体に適用されます。

データの取得はuseQueryを使用する

hooks/useQueryPosts.ts

import axios from 'axios'
import { useQuery } from 'react-query'

type Post = {
  userId: number,
  id: number
  title: string
  body:string
}

export const useQueryPosts = () => {
  const getPosts = async () => {
    const { data } = await axios.get<Post[]>(
      "https://jsonplaceholder.typicode.com/posts"
    )
    return data
  }

  return useQuery<Post[], Error>('posts', posts, {
    staleTime: 0,
    refetchOnWindowFocus: true,
    //cacheTime: 5000,
    //refetchInterval: 5000,
  })
}

  • staleTime
    デフォルトは0
    キャッシュしたデータが古いとみなされるまでの時間をミリ秒単位で指定できます。
    "Infinity"にするとデータが古いと判断されることがなくなります。
  • cacheTime
    デフォルトは 5 * 60 * 1000 (5分)
    キャッシュする時間を残る時間をミリ秒単位で指定します。
    "infinity"にすると残り続けます。
  • refetchInterval
    指定した数値で継続的にrefetchできます。(ポーリング)

使用例

import { useQueryPosts } from '../hooks/useQueryPosts'

export const Posts = () => {
  const { data, isLoading, isError } = useQueryPosts()

  if (isLoading) return <div>Loading...</div>
  if (isError) return <div>Error</div>

  ...

}

returnされるデータ
https://react-query.tanstack.com/reference/useQuery#_top

  • data
    最後に解決したクエリー結果
    デフォルトはundefined
  • error
    非同期関数からスローされたエラー内容
    デフォルトはnull
  • isLoading(Boolean)
    ローディング中(キャッシュされたデータがなく現在フェッチ中)
  • isError(Boolean)
    クエリーの試行結果がエラーとなった場合

データの更新はuseMutationを使用

  • こちらもサンプルでJSONPlaceholderを使用してます。
  • POST (.../posts)
  • PUT (.../posts/1)
  • DELETE (.../posts/1)

hooks/useMutatePost.ts

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

type Post = {
  userId: number,
  id: number
  title: string
  body:string
}

export const useMutatePost = () => {
  const queryClient = useQueryClient()

  const createPostMutation = useMutation(
    (post: Pick<Post, 'title' | 'body'>) =>
      axios.post<Post>('https://jsonplaceholder.typicode.com/posts', post),
    {
      onSuccess: (res) => {
        const previousPosts = queryClient.getQueryData<Post[]>('posts')
        if (previousPosts) {
          queryClient.setQueryData<Post[]>('posts', [
            ...previousPosts,
            res.data,
          ])
        }
      },
    }
  )
  const updatePostMutation = useMutation(
    (post<Omit, "userId">) =>
      axios.put<Post>(
        `https://jsonplaceholder.typicode.com/posts/${post.id}`,
        post
      ),
    {
      onSuccess: (res, variables) => {
        const previousPosts = queryClient.getQueryData<Post[]>('posts')
        if (previousPosts) {
          queryClient.setQueryData<Post[]>(
            'posts',
            previousPosts.map((post) =>
              post.id === variables.id ? res.data : post
            )
          )
        }
      },
    }
  )
  const deletePostMutation = useMutation(
    (id: number) =>
      axios.delete<Post>(`https://jsonplaceholder.typicode.com/posts/${id}`),
    {
      onSuccess: (res, variables) => {
        const previousPosts = queryClient.getQueryData<Post[]>('posts')
        if (previousPosts) {
          queryClient.setQueryData<Post[]>(
            'posts',
            previousPosts.filter((post) => post.id === variables)
          )
        }
      },
    }
  )
  return { createPostMutation, updatePostMutation, deletePostMutation }
}

https://react-query.tanstack.com/reference/useMutation
getQueryDataで現在キャッシュされているデータを取得し、setQueryDataで新たなデータをセットしてキャッシュを更新しています。

使用例

export const PostCreate: FC = () => {
  const { createPostMutation } = useMutatePost()

  const postCreate = (post: Pick<Post, 'title' | 'body'>) => {
    createPostMutation.mutate(post)
  }
  if (createPostMutation.isLoading) return <div>Creating...</div>

  ...

}

最後に

まだまだ勉強不足なところが沢山あるので、また調べながら補足できればと思います。

2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?