TanStack Query入門
#React
#TanStack Query
はじめに
- TanStack Query(旧React Query)は、非同期データの取得・キャッシュ・同期を簡単に行えるライブラリです
- useEffectとuseStateを使った従来のデータフェッチの複雑さを解消してくれます
- React以外にも、Vue、Solid、Svelteなど様々なフレームワークに対応しています
なぜTanStack Queryを使うのか
従来のデータフェッチの問題点
useEffectとuseStateを使った従来のパターンでは、多くのボイラープレートが必要です:
function UserProfile({ userId }: { userId: string }) {
const [user, setUser] = useState<User | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
setIsLoading(true);
fetch(`/api/users/${userId}`)
.then((res) => res.json())
.then((data) => {
setUser(data);
setIsLoading(false);
})
.catch((err) => {
setError(err);
setIsLoading(false);
});
}, [userId]);
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <div>{user?.name}</div>;
}
このパターンには以下の問題があります:
- ローディング・エラー・データの3つの状態を手動で管理する必要がある
- キャッシュがないため、同じデータを何度もフェッチしてしまう
- コンポーネントがアンマウントされた後にstateを更新しようとする問題
- 複数のコンポーネントで同じデータを使う場合の共有が難しい
TanStack Queryで解決
TanStack Queryを使うと、上記のコードはこうなります:
function UserProfile({ userId }: { userId: string }) {
const { data: user, isLoading, error } = useQuery({
queryKey: ['user', userId],
queryFn: () => fetch(`/api/users/${userId}`).then((res) => res.json()),
});
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <div>{user?.name}</div>;
}
インストール
npm install @tanstack/react-query
セットアップ
アプリケーションのルートでQueryClientProviderを設定します:
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<YourApp />
</QueryClientProvider>
);
}
基本的な使い方
useQuery - データの取得
useQueryはデータを取得するための基本的なフックです:
import { useQuery } from '@tanstack/react-query';
function TodoList() {
const { data, isLoading, error } = useQuery({
queryKey: ['todos'],
queryFn: async () => {
const response = await fetch('/api/todos');
return response.json();
},
});
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error occurred</div>;
return (
<ul>
{data.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
}
queryKeyについて
- queryKeyはクエリを一意に識別するためのキーです
- 配列形式で指定し、依存する値を含めることでキャッシュを適切に管理できます
- 例:
['todos']、['todo', todoId]、['todos', { status: 'done' }]
useMutation - データの更新
useMutationはデータの作成・更新・削除に使用します:
import { useMutation, useQueryClient } from '@tanstack/react-query';
function AddTodo() {
const queryClient = useQueryClient();
const mutation = useMutation({
mutationFn: (newTodo: { title: string }) => {
return fetch('/api/todos', {
method: 'POST',
body: JSON.stringify(newTodo),
});
},
onSuccess: () => {
// 成功時にtodosのキャッシュを無効化して再取得
queryClient.invalidateQueries({ queryKey: ['todos'] });
},
});
return (
<button
onClick={() => mutation.mutate({ title: 'New Todo' })}
disabled={mutation.isPending}
>
{mutation.isPending ? 'Adding...' : 'Add Todo'}
</button>
);
}
キャッシュの設定
TanStack Queryの強みはキャッシュ管理です。主要なオプションを紹介します:
const { data } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
staleTime: 1000 * 60 * 5, // 5分間はキャッシュを新鮮とみなす
gcTime: 1000 * 60 * 30, // 30分間キャッシュを保持(旧cacheTime)
});
- staleTime: データが「古い」とみなされるまでの時間。この間は再フェッチしない
- gcTime: 使われなくなったキャッシュがガベージコレクションされるまでの時間
DevToolsの活用
開発時にはDevToolsを使うとキャッシュの状態を可視化できます:
npm install @tanstack/react-query-devtools
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
function App() {
return (
<QueryClientProvider client={queryClient}>
<YourApp />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
}
まとめ
- TanStack Queryを使うことで、非同期データの取得・キャッシュ管理が大幅に簡単になります
- useQueryでデータ取得、useMutationでデータ更新を行います
- queryKeyを適切に設定することで、効率的なキャッシュ管理が可能です
- DevToolsを活用して、キャッシュの状態をデバッグできます