TanStack query を使うと、データの取得や、更新時のキャッシュ、古いデータ周りのことを簡単に扱うことができます。この記事では、create-react-app でアプリ作成後 TanStack query のデータの読み込みと、更新の基本的な使用例を確認することができます。
アプリ作成とパッケージをインストール
react アプリを作成します。
create-react-app アプリ名
TanStack query パッケージをインストールします。
npm install @tanstack/react-query
ファイル構成
src//
|-- api//
| `-- comments.js
|-- App.js
`-- index.js
TanStack query を使う
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient()
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
);
11, 13: QueryClientProvider で App コンポーネントを囲います。
サーバーからデータを取得
例では、ローディング時間を確認するために、遅らせてデータの取得と、更新の処理を行います。
let Comments = [
{ id: 1, comment: "Hello" },
{ id: 2, comment: "World" },
]
export const getComment = () => {
return delay().then(
res => [...Comments],
err => Promise.reject({ err }))
}
export const addComment = (input) => {
return delay(200).then(
res => {
Comments.push({ id: Comments.length + 1, comment: input })
return Comments
},
err => Promise.reject({ err })
)
}
async function delay(ms = 500) {
return new Promise(resolve => setTimeout(resolve, ms))
}
useQuery
useQuery はデータを読み込むときに使用します。
import { useQuery } from '@tanstack/react-query'
import { getComment } from './api/comments';
function App() {
const query = useQuery({
queryKey: ["comments"],
queryFn: () => getComment(),
})
if (query.isLoading) return <h1>Loading...</h1>
if (query.isError) return <h1>{JSON.stringify(query.error)}</h1>
return (
<div className="App">
{query.data.map(res => (
<div key={res.id}>{res.id} {res.comment}</div>
))}
</div>
);
}
export default App;
6: queryKey はアプリケーション全体でクエリを再取得、キャッシュ、および共有するために内部的に使用されます。
7: queryFn データまたは、エラーをスローする promise を返す関数を指定します。
さらにオプションを追加することで、データの再取得のタイミング、キャッシュの保存期間などを指定することができます。
10, 11: ローディング中、エラーの状態を取得することができます。
Mutation
Mutation では、データの作成/更新/削除を行うことができます。
データの更新
フォームから入力された値でデータを更新します。
import { useQuery, useMutation } from '@tanstack/react-query'
import { useRef } from 'react';
import { addComment, getComment } from './api/comments';
function App() {
const inputRef = useRef(null);
const query = useQuery({
queryKey: ["comments"],
queryFn: () => getComment(),
})
const mutation = useMutation({
mutationFn: input => addComment(input),
onSuccess: (data, variables, context) => {
//ミューテーションが成功すると起動し、ミューテーションの結果が渡されます。
},
onMutate: variables => {
//ミューテーション関数が起動される前に起動し、ミューテーション関数が受け取るのと同じ変数が渡されます。
return variables + 'context' //context
}
})
const submit = () => {
mutation.mutate(inputRef.current.value)
}
if (query.isLoading) return <h1>Loading...</h1>
if (query.isError) return <h1>{JSON.stringify(query.error)}</h1>
return (
<div className="App">
{query.data.map(res => (
<div key={res.id}>{res.id} {res.comment}</div>
))}
{mutation.isLoading ? (
'isAdding'
) : <>
{mutation.isError ? (
<div>{JSON.stringify(mutation.error.err)}</div>
) : null}
</>}
<input type="text" ref={inputRef} />
<button onClick={submit}>Submit</button>
</div>
);
}
export default App;
13: ミューテーション関数、フォームから入力された値を渡して、データを更新します。
14: ミューテーションが成功時に起動します。data
はミューテーション関数からの戻り値、variables
はフォームの値、context
はonMutate の戻り値になります。
17: この関数は、ミューテーション関数が起動される前に起動し、ミューテーション関数が受け取るのと同じ変数が渡されます。
24: ミューテーションに値を渡します。
35~41: ローディング、エラーメッセージを表示させています。
データの再読み込み
データの再読み込みは、QueryClient
をミューテーションの成功時に使用します。
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
const queryClient = useQueryClient();
const mutation = useMutation({
mutationFn: input => addComment(input),
onSuccess: (data, variables, context) => {
queryClient.invalidateQueries(["comments"])
// queryClient.setQueryData(["comments"], data)
},
onMutate: variables => {
return variables + 'context' //context
}
})
7: invalidateQueries
にqueryKey を渡して、再読み込みを行います。
8: データの再読み込みが必要なく、キャッシュのみを更新したい場合は、 setQueryData
を使用することもできます。
以上です。