TanstackQueryとは?
TanstackQueryとは、データ取得する際に使われるライブラリです。
公式ドキュメントから引用するとWebアプリケーションでのサーバー状態の取得、キャッシュ、同期、更新が非常に簡単になります。
公式ドキュメント
インストール
React(npm)で進めて行きます。yarnを使っているならyarn、pnpmならpnpmでやってください。
コマンドが少し変わるので公式ドキュメントから確認してください。
npm i @tanstack/react-query
従来のデータフェッチ(インターネット上から情報を取ってくること)のやり方
以前はuseEffectやuseStateなどを使っていました。
import { useState, useEffect } from 'react'
import axios from 'axios'
const Posts = () => {
const [data, setData] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchPosts = async () => {
try {
setIsLoading(true);
const response = await axios.get(
"***********"
);
setData(response.data);
setError(null);
} catch (err) {
setError(err.message);
} finally {
setIsLoading(false);
}
};
fetchPosts();
}, []); // 空配列 = コンポーネントが最初に表示されたときだけ実行
if (isLoading) return <div>読み込み中...</div>;
if (error) return <div>エラー: {error}</div>;
return (
<div>
<h1>投稿一覧</h1>
<div>{data.map((post) => (
<p key={post.id}>
<a href="/">{post.title}</a>
</p>
))}</div>
</div>
)
}
export default Posts
従来のやり方の問題点
上記のコードくらいのuseStateやuseEffectの数なら、そんなに大した問題ではないのですが、
実際に稼働しているWebサービスだったらどうでしょうか?
大規模アプリで発生する問題
1.同じコードの繰り返し
APIからデータを取得するたびに、毎回以下を書く必要があります。💦
const [data, setData] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => { /* データ取得処理 */ }, []);
APIが10、20、100と増えていくたびに、このコードも同じだけ増えていきます。😱
2.重複したデータ取得
//Postsページ → ユーザー情報を取得
// Profileページ → 同じユーザー情報をまた取得
// Headerコンポーネント → また同じユーザー情報を取得
// → 無駄なAPI呼び出しが大量発生!
3.キャッシュ管理が大変
一度取得したデータを再利用したいけど、データが古くなったら再取得したい
この管理を自分でやるのは非常に大変😅
4.状態管理の複雑化
大量のuseStateとuseEffectを書くと、どこで何を管理しているのか分からなくなります。😭
コードが肥大化してぐちゃぐちゃになって行きます。
これらを解決するために生まれたのが
TanstackQueryです。
TanstackQueryでのデータフェッチ
queryClientをインスタンス化して、QueryClientProviderでComponentを囲みます。
import './App.css'
import Posts from './components/Posts'
import {
QueryClient,
QueryClientProvider,
} from '@tanstack/react-query'
const queryClient = new QueryClient() // queryClientをインスタンス化
function App() {
// QueryClientProviderでComponentを囲む
return (
<QueryClientProvider client={queryClient}>
<Posts />
</QueryClientProvider>
)
}
export default App
useQueryを呼び出す
useQueryを呼び出していく必要があります。はjsonplaceholderを使ってます。
ここでデータを取得してきて、画像はjsonplaceholderから取得してきたものです。
動画はわかりやすいので良かったら見てみてください。
あとコードはかなりシンプルになったかと思います。
import { useQuery } from '@tanstack/react-query'
import axios from 'axios'
const Posts = () => {
const { data, isLoading, error } = useQuery({
queryKey: ["posts"],
queryFn: async () => {
const { data } = await axios.get(
"https://jsonplaceholder.typicode.com/posts"
);
return data;
},
});
if (isLoading) return <div>読み込み中...</div>;
if (error) return <div>エラー: {error.message}</div>;
return (
<div>
<h1>投稿一覧</h1>
<div>{data.map((post) => (
<p key={post.id}>
<a href="/">{post.title}</a>
</p>
))}
</div>
</div>
)
}
export default Posts
導入メリット
1.コードがシンプルになる
useStateやuseEffectを自分で書く必要がなく。
ローディング、エラー、データの状態を自動管理
2.自動キャッシュ機能
一度取得したデータは自動でキャッシュされ、
同じデータを複数のコンポーネントで使っても、API呼び出しは1回だけで済みます。
3.自動で再取得
データが古くなったら自動で再取得して、
ウィンドウにフォーカスが戻ったら最新データを取得します。
4.保守性の向上
データ取得のロジックが一箇所に集約するので、大規模アプリでも管理しやすいです。
結論(TanStack Queryはなぜ生まれたか)
大規模なアプリで発生する「無駄なデータ取得」と「煩雑な状態管理」を解決するために生まれました。
参考動画
useEffectよりも優れたデータフェッチング方法【TanstackQuery入門】
説明
補足
ClaudeCodeにも文章を書くの少し手伝ってもらっています。
