インストール
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を設定すると全体に適用されます。
-
retry
通信が失敗した場合、自動的にクエリを再試行するかどうか。(数値でリクエスト回数も指定可能)
https://react-query.tanstack.com/guides/query-retries#_top -
refetchOnWindowFocus
windowをfocusした際に自動的に再取得するかどうか
trueに設定すると、データが古い場合、windowのfocus時に再取得
"always"に設定すると、常にwindowのfocus時に再取得される。
https://react-query.tanstack.com/reference/useQuery#_top
データの取得はuseQueryを使用する
- サンプルでJSONPlaceholderを使用してます。
- GET(/posts/1)
https://jsonplaceholder.typicode.com/
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>
...
}
最後に
まだまだ勉強不足なところが沢山あるので、また調べながら補足できればと思います。