
しかし、画面遷移のたびに同じデータを取得する、別のコンポーネントでも同じAPIを呼ぶ、ウィンドウへ戻ったときに最新状態を確認する、といった要件が加わると、少しずつ事情が変わります。ローディング状態、エラー状態、再取得、キャッシュ、有効期限、重複リクエストの抑制まで自分で管理する必要があり、フックの中身が通信処理よりも状態管理のコードで埋まっていくためです。
特にReactの開発環境では、useEffectの実行タイミングやコンポーネントの再マウントによって、同じリクエストが複数回発生しているように見えることがあります。ここでAxiosを別の通信ライブラリへ置き換えても、キャッシュや再フェッチの仕組みが自動的に整うわけではありません。AxiosとTanStack Queryは競合する選択肢ではなく、担当する層が違うものとして考えると、導入の判断がしやすくなります。
この記事では、TanStack Queryと自作Axiosフックを比較しながら、どの段階でAPIキャッシュを導入すべきか、Axiosを残したままどのように移行できるかを、仕組みから整理していきます。
AxiosとTanStack Queryは、そもそも比較する層が違う
「TanStack QueryとAxiosのどちらを選ぶべきか」と考え始めると、最初に迷いやすいのがこの部分です。結論から言うと、AxiosはHTTP通信を担当し、TanStack Queryはサーバー状態の管理を担当します。
AxiosはPromiseベースのHTTPクライアントです。GETやPOSTなどのリクエストを送信し、レスポンスを受け取り、JSONを扱いやすい形に変換します。認証用のヘッダーを付けたり、タイムアウトを設定したり、リクエスト・レスポンスのインターセプトを設定したりできるため、LaravelやWordPressのAPIを呼び出す通信層として使いやすいライブラリです。
一方、TanStack Queryが扱うのは、通信そのものよりも、その通信結果をアプリケーション内でどう管理するかという問題です。
たとえば、次のような処理を担当します。
- 取得したデータを一定期間キャッシュする
- 同じクエリを複数のコンポーネントが使っている場合に、リクエストを重複させない
- ウィンドウへ戻ったときや、一定条件を満たしたときに再フェッチする
- 一時的な通信エラーに対して再試行する
- ローディング中、エラー時、取得成功後の状態を管理する
- 更新処理のあとに関連するキャッシュを無効化する
- 画面からコンポーネントが消えたあとも、必要に応じてデータを保持する
つまり、Axiosが「APIへ荷物を届ける配送手段」だとすれば、TanStack Queryは「その荷物をいつ取り寄せ、どこに保管し、いつ更新するかを管理する仕組み」です。両者を同時に使うことに矛盾はありません。
Axiosは通信の道具であり、TanStack Queryは通信結果を扱うための状態管理の仕組みです。比較するときは、置き換えではなく役割分担として見てみましょう。
この整理ができると、認証用のAxiosインスタンスをすでに用意しているLaravel連携のプロジェクトでも、通信部分を大きく作り直さずにTanStack Queryを導入できます。useQueryのqueryFnの中から、インターセプト設定済みのAxiosインスタンスを呼び出せばよいからです。
自作Axiosフックは、どこまでなら扱いやすいのか
自作フックの基本的な構成は、比較的単純です。コンポーネントが表示されたらuseEffectでAxiosのリクエストを実行し、受け取ったデータをuseStateへ保存します。通信中はローディング状態をtrueにし、失敗したらエラー状態へ切り替えるという流れでしょう。
この構成が悪いわけではありません。次のような条件なら、十分に現実的な選択肢です。
- その画面で一度だけデータを取得すればよい
- 取得結果を別の画面やコンポーネントで共有しない
- 更新頻度が低く、画面へ戻ったときの再フェッチも必要ない
- キャッシュの有効期限を細かく制御する必要がない
- 送信処理の成功・失敗だけを扱えばよい
- プロジェクトの規模が小さく、状態管理のルールを増やしたくない
たとえばログイン処理やログアウト処理のような単発の送信は、直接Axiosを呼び出して処理する方が自然な場合があります。キャッシュを作る必要がない処理まで、すべてTanStack Queryのクエリとして扱う必要はありません。
難しくなるのは、取得処理がプロジェクトの複数箇所へ広がったときです。自作フックでは、最初のうちは次のような状態を持っているだけかもしれません。
dataisLoadingerror
ところが、実際の開発では次第に状態が増えていきます。初回取得中なのか、既存データを表示したまま再取得しているのか、リクエストを手動で再実行できるのか、コンポーネントがアンマウントされたあとにレスポンスが返ってきたらどうするのか、といった判断が必要になるためです。
さらに、同じAPIを複数の場所で呼び出すと、次のような問題が起こりやすくなります。
同じデータを複数回取得してしまう
一覧コンポーネントとサイドバーの両方で、同じユーザー情報やカテゴリ情報を取得しているとします。自作フックは、それぞれのコンポーネントに独立して存在するため、同じURLに対して別々のリクエストを送る可能性があります。
その結果、通信回数が増えるだけではありません。レスポンスが返るタイミングによって、コンポーネントごとに異なる内容が表示されることもあります。
キャッシュの更新漏れが起こる
POSTやPUTでデータを更新したあと、どの自作フックの状態を更新すべきかを把握し続ける必要があります。ある画面では最新データが表示されているのに、別の画面では古いデータが残っているという状態は、API連携ではよくあるつまずきです。
リクエストのキャンセルや競合を考える必要がある
検索条件が短時間に変わる画面では、古い検索リクエストのレスポンスが、新しい検索結果よりあとに返ることがあります。この場合、古いレスポンスで画面の状態が上書きされる可能性があります。
AbortControllerなどを使ってリクエストをキャンセルしたり、現在の検索条件とレスポンスの対応関係を確認したりする処理が必要になります。こうした対応は一度書けば終わりではなく、似た画面を作るたびに再利用できる形へ整える必要があります。
再試行や再フェッチのルールが分散する
通信エラーが起きたときに何回再試行するか、ウィンドウへ戻ったときに再取得するか、一定時間を過ぎたら古いデータと判断するか、といったルールを自作フックごとに実装すると、プロジェクト全体で挙動が揃わなくなります。
このあたりが、自作Axiosフックの保守コストを押し上げるポイントです。単純な通信処理が複雑になるのではなく、通信に付随する状態管理と再現性のあるルールが増えていきます。
TanStack Queryが追加する「サーバー状態」の仕組み
TanStack Queryを導入すると、APIから取得したデータは、コンポーネントが個別に持つ状態ではなく、クエリキーに紐づいたサーバー状態として管理されます。
ここで大切なのが、クエリキーです。たとえばユーザー一覧なら['users']、特定のユーザーなら['users', userId]のように、データの識別に使うキーを決めます。同じキーを持つクエリは、同じサーバーデータを参照することになります。
そのため、複数のコンポーネントで同じクエリを使っても、毎回個別に状態を用意する必要がありません。データの取得状態やキャッシュが共有されるので、一覧画面と詳細画面の間で同じ情報を扱う場合にも、仕組みを組み立てやすくなります。
TanStack Queryと自作Axiosフックの違いを、実装上の観点で整理すると次のようになります。
| 比較項目 | 自作Axiosフック | TanStack Query |
|---|---|---|
| HTTPリクエスト | Axiosで実装 | AxiosなどをqueryFnから呼び出す |
| ローディング状態 | useStateなどで手動管理 | クエリの状態として提供 |
| エラー状態 | try-catchなどを自作 | クエリの状態として管理 |
| キャッシュ | 自分で保存・更新処理を実装 | クエリキーを軸に自動管理 |
| 重複リクエスト | 自作対応が必要 | クエリ単位で抑制しやすい |
| 再フェッチ | useEffectやイベント処理を自作 | 条件を設定して制御 |
| 失敗時の再試行 | 自作実装 | 標準機能として設定可能 |
| 更新後の反映 | 各状態を手動で更新 | キャッシュ無効化や再取得で統一 |
| 小規模な単発処理 | 軽量で扱いやすい | 導入すると構成が増える場合がある |
| 複数画面でのデータ共有 | 実装が複雑になりやすい | クエリキーで整理しやすい |
TanStack Queryでは、データが「新しいかどうか」をstaleTimeで考えます。取得直後のデータを一定時間は新しいものとして扱う設定で、短時間に同じAPIを何度も呼び出すことを防ぎます。
一方、gcTimeは、使われなくなったクエリデータをどの程度保持するかに関係します。以前のバージョンでcacheTimeと呼ばれていた設定は、TanStack Query v5ではgcTimeという名称になっています。名前が変わっただけに見えますが、実際には「データが新しいか」と「使われなくなったデータをいつ片付けるか」は別の問題です。
ここを混同すると、次のような設定ミスにつながります。
staleTimeを長くしたので、キャッシュが永遠に残ると思ってしまうgcTimeを長くしたので、データが常に最新だと思ってしまう- 画面へ戻ったときの再フェッチを止めたいのに、別の設定を変更してしまう
staleTimeは再検証の判断、gcTimeは未使用データの保持に関する設定です。それぞれの役割を分けて考えると、APIキャッシュの設計が安定します。
「自作から移行するべきか」を判断する境目
TanStack Queryを使うかどうかは、APIの数だけで決めるものではありません。むしろ、同じデータをどの範囲で共有するか、更新後にどの画面を同期させる必要があるかが判断材料になります。
自作フックを維持しやすいケース
個人開発の初期段階では、すぐにTanStack Queryへ移行しなくても問題ありません。次のような場合は、自作フックの仕組みを保ったままでも、十分に再現性のある実装ができます。
- 画面ごとに取得するデータが明確に分かれている
- 取得したデータを同じ画面内でしか使わない
- ページを開いたときの初回取得だけで要件を満たせる
- 更新処理のあとに再取得する対象が少ない
- API通信の失敗時に自動再試行が必要ない
- チームやプロジェクトで状態管理の規模を増やしたくない
ただし、「今は小さいから」という理由だけで、将来の拡張をまったく考えなくてよいわけではありません。自作フックを残すなら、少なくともデータ取得、エラー変換、認証エラーの扱い、キャンセル処理の責務を整理しておくと、あとから移行しやすくなります。
TanStack Queryを導入しやすいケース
次の条件が重なるほど、TanStack Queryの効果が出やすくなります。
1. 複数のコンポーネントが同じAPIデータを参照している
ユーザー情報、権限、商品カテゴリ、通知件数などは、アプリケーションの複数箇所で使われがちです。個別のuseStateで持つより、クエリキーを決めて共有した方が状態の流れを追いやすくなります。
2. 画面へ戻ったときの再検証が必要になる
管理画面やダッシュボードでは、別のタブでデータが変更されることがあります。ウィンドウフォーカス時の再フェッチを利用すると、ユーザーが手動で更新ボタンを押さなくても、古い状態を確認する機会を減らせます。
3. 更新後に関連データをまとめて同期したい
商品を更新したあとに商品一覧と商品詳細を更新する、記事を公開したあとに記事一覧と公開状態を更新する、といった処理では、キャッシュの無効化ルールが重要になります。
4. 一時的な通信エラーへの対応を共通化したい
TanStack Queryには失敗時の再試行があり、既定では3回の再試行が行われます。ただし、認証エラーや入力エラーまで同じように再試行するのは適切ではないため、ステータスコードやエラーの種類に応じた調整は必要です。
5. 自作フックが画面ごとに似た形で増えている
useUsers、usePosts、useCategoriesのようなフックが増え、それぞれにローディング、エラー、再取得、キャッシュ更新の処理が書かれているなら、共通の仕組みに置き換える価値があります。データフェッチ部分のコード量が、体感で約60〜70%程度減るとされるケースがあるのも、この重複が整理されるためです。
ここで注意してほしいのは、TanStack Queryを入れればすべての状態管理が不要になるわけではないという点です。サーバーから取得したデータはTanStack Queryが得意ですが、モーダルの開閉、入力途中のフォーム、タブの選択状態など、ブラウザ内だけで完結する状態は、useStateや別の状態管理手段で扱う方が自然です。
Axiosを残したままTanStack Queryを使う構成
すでにAxiosを使っているプロジェクトでは、TanStack Queryを導入するためにAxiosを捨てる必要はありません。むしろ、認証や共通エラー処理が整っているなら、そのAxiosインスタンスを活用した方が安全です。
たとえば、LaravelのAPIへ接続する場合、Axios側に次のような設定を持たせることがあります。
- APIのベースURL
- 認証トークン
AcceptやContent-Typeなどのヘッダー- タイムアウト
- レスポンスの共通エラー処理
- 認証期限切れ時のログアウトやログイン画面への遷移
これらはHTTP通信の責務なので、TanStack Queryへ移す必要はありません。TanStack QueryのqueryFnでは、その設定済みインスタンスを使ってAPIを呼び出します。
役割分担は次のように考えると整理しやすくなります。
- Axiosインスタンス:APIへどう接続するかを決める
queryFn:どのエンドポイントから何を取得するかを決める- クエリキー:取得したデータをどの単位で識別するかを決める
- TanStack Query:取得結果をいつ使い、いつ再検証するかを管理する
- コンポーネント:画面に何を表示するかを決める
この構成にすると、通信方式と状態管理の仕組みを分離できます。Laravel側の認証方式を変更した場合でも、Axiosインスタンスの調整に閉じ込めやすくなりますし、キャッシュの保持時間を変更したい場合はTanStack Query側の設定に集中できます。
クエリキーはURLの別名ではありません
移行時に最も注意してほしいのが、クエリキーの設計です。単にAPIのURLを文字列として入れるのではなく、画面上でどのデータとして扱うかを表すキーにします。
たとえば、投稿一覧と投稿詳細を同じ['posts']としてしまうと、異なる形のデータを同じキャッシュとして扱う危険があります。投稿一覧なら['posts', 'list', 条件]、詳細なら['posts', 'detail', postId]のように、用途と識別子を分けた方が後の無効化処理を設計しやすくなります。
検索条件、ページ番号、並び順などもデータの内容に影響するため、クエリキーに含める必要があります。検索条件をキーへ含めずに同じキャッシュを使うと、条件を変更しても前の検索結果が表示される原因になります。
staleTimeをゼロのままにしない
TanStack Queryを導入した直後は、取得したデータがすぐに古い状態として扱われる設定になっていることがあります。その場合、キャッシュは利用されても、状況によっては再フェッチが起こりやすくなります。
もちろん、常に最新情報が必要なデータなら短いstaleTimeが適しています。しかし、都道府県一覧、商品カテゴリ、権限の定義など、数分程度の遅れが画面上の問題にならないデータまで頻繁に取り直す必要はありません。
データの性質ごとに、次のような考え方で分けてみましょう。
- ほとんど変わらないマスターデータ:比較的長い
staleTime - 数分単位で更新される一覧:中程度の
staleTime - 在庫や通知件数など変化が多い情報:短い
staleTimeや明示的な再取得 - ユーザー操作の直後に必ず反映したいデータ:更新処理後の無効化と再フェッチ
数字を先に決めるのではなく、「古いデータを何分まで許容できるか」を業務上の要件から決めるのがポイントです。
取得処理と更新処理は、同じ考え方で扱わない
TanStack Queryを導入すると、すべてのAPI操作をuseQueryへ寄せたくなるかもしれません。しかし、取得と更新では、データの性質が異なります。
useQueryは、基本的にサーバーからデータを取得し、その状態を管理するための仕組みです。一方、登録、更新、削除などの操作は、ユーザーの明確な操作をきっかけに実行する処理です。このような処理には、ミューテーションの仕組みを使う方が意図を表現しやすくなります。
たとえば記事を更新する場合、更新処理が成功したら記事詳細のキャッシュを無効化し、必要であれば記事一覧のキャッシュも再取得します。ここで大切なのは、更新APIのレスポンスをそのまま画面全体へ手作業で配るのではなく、どのクエリが古くなったかを明示することです。
更新後の同期には、主に次の考え方があります。
- 更新成功後に対象クエリを無効化し、次の表示タイミングで再取得する
- 更新成功時のレスポンスで、対象キャッシュを直接更新する
- 一覧と詳細で異なるキャッシュを持つ場合、それぞれの関係を定義する
- 更新失敗時には、画面上の入力状態を維持したままエラーを表示する
小さな画面であれば、更新成功後に再取得するだけでも十分です。楽観的更新のような高度な仕組みは、通信待ち時間が体験上の問題になる場合や、編集操作を頻繁に行う画面で検討すればよいでしょう。
ログイン、ログアウト、パスワードリセットのような単発処理も、必ずクエリとして扱う必要はありません。キャッシュが不要な操作では、Axiosを直接呼び出す方がコードの意図が明確になる場合があります。TanStack Queryを導入する目的は、ライブラリを使うことではなく、サーバー状態の管理を安定させることです。
バージョン変更でつまずきやすいポイント
TanStack Queryは、React QueryからTanStack Queryへ名称が変わり、2022年には複数のフレームワークに対応するTanStack Query v4が登場しました。その後、v5ではキャッシュ仕様やフックAPIの整理が進んでいます。
そのため、古い記事やサンプルをそのまま現在のプロジェクトへ適用すると、オプション名や呼び出し方の違いでエラーになることがあります。特に次の点には注意してください。
cacheTimeとgcTimeの違い
以前のバージョンで使われていたcacheTimeは、v5ではgcTimeという名前になっています。プロジェクトの依存バージョンと、参照しているドキュメントのバージョンが合っているかを確認しましょう。
設定値の意味も、単に「キャッシュを何分残すか」と覚えるより、「誰にも使われていないクエリをいつガベージコレクションするか」と理解した方が混乱しにくくなります。
オプションの書き方を確認する
TanStack Queryのバージョンによっては、クエリやミューテーションのオプション指定方法が変わっています。古いサンプルでは位置引数を使っているのに、現在の環境ではオブジェクト形式が基本になっていることがあります。
エラーが出たときは、コードの一部だけを修正する前に、次の情報をそろえて確認してみましょう。
@tanstack/react-queryのバージョン- Reactのバージョン
- TypeScriptの設定
- 参照している記事や公式ドキュメントの対象バージョン
QueryClientProviderがアプリケーションのルートに配置されているか
開発環境の重複リクエストを本番の障害と混同しない
Reactの開発環境では、意図しない副作用を見つけるために、コンポーネントの処理が通常と異なる形で確認される場合があります。これにより、useEffectの中でリクエストを送っていると、開発中だけ同じ通信が複数回発生したように見えることがあります。
この現象を隠すために、フラグを追加して無理に一回だけ実行する処理を書くと、根本的なライフサイクルの理解を妨げることがあります。TanStack Queryを使う場合でも、開発環境の通信ログだけを見て判断せず、クエリキー、キャッシュ、再フェッチ条件がどのように作用しているかを確認しましょう。
自作Axiosフックから移行する手順
既存のコードを一度にすべて書き換える必要はありません。むしろ、通信量が多く、重複やキャッシュ更新の問題が起きている画面から小さく移行した方が、変更の影響を確認しやすくなります。
まず通信層を分離する
最初に、自作フックの中へ直接書かれているAxiosの設定を見直します。APIのベースURL、認証、共通ヘッダー、エラー処理などを、共通のAxiosインスタンスへまとめていきます。
この作業を先に行う理由は、TanStack Queryの導入と認証処理の変更を同時に起こさないためです。通信層が整理されていれば、移行後の問題がキャッシュ由来なのか、Axios由来なのかを切り分けやすくなります。
次にクエリキーを設計する
対象画面で扱っているデータを、一覧、詳細、検索結果、関連データなどに分けます。クエリキーは後からキャッシュを無効化するときの基準になるため、URLの文字列を適当に並べるのではなく、データの意味に合わせて名前を付けてみましょう。
たとえば、投稿に関するデータなら、一覧と詳細、公開済み一覧、管理画面用一覧を同じ種類として扱うのか、それとも別データとして扱うのかを決めます。ここが曖昧なままだと、更新後にどのキャッシュを無効化するべきか判断できなくなります。
useEffectの取得処理をクエリ関数へ移す
自作フックで行っていたAxiosの取得処理を、TanStack Queryのクエリ関数へ移します。ここでは、レスポンス全体を返すのか、レスポンス内のデータだけを返すのかを決めておくと、コンポーネント側の型が安定します。
Axiosのレスポンスには、データ本体のほかにステータスやヘッダーも含まれます。画面側でステータスを直接使わないなら、クエリ関数ではデータ本体を返す方が扱いやすいでしょう。ただし、ページネーション情報をヘッダーで返しているAPIでは、必要な情報を失わないように設計してください。
状態分岐をライブラリの状態へ置き換える
自作フックにあるisLoading、error、dataの状態を、TanStack Queryが提供する状態へ置き換えます。ここで、初回取得中と再取得中を同じ表示にしないことが大切です。
初回取得中なら画面全体にローディング表示を出してもよいですが、すでにデータを表示している状態でバックグラウンド再フェッチが始まった場合は、画面を消さずに小さな更新表示を出す方が自然です。サーバー状態のライフサイクルを分けて考えると、操作中の画面がちらつきにくくなります。
更新処理後のキャッシュを決める
最後に、登録や更新、削除の処理が成功したあと、どのクエリを無効化するかを定義します。ここを省略すると、更新APIは成功しているのに、画面には古いデータが残るという問題が起こります。
移行対象の画面だけでなく、同じデータを参照している画面を確認しておくと安心です。管理画面で記事を更新したあと、公開側のプレビューや一覧にも影響するなら、関連するクエリの範囲を決めておく必要があります。
LaravelやWordPressのAPIと組み合わせるときの注意点
フロントエンドだけでなく、LaravelやWordPress側のAPI設計もキャッシュの扱いやすさに影響します。
まず、一覧APIのレスポンス形式を安定させておきましょう。ページ番号、総件数、次ページの有無などがレスポンスごとに異なると、フロントエンド側でクエリキーやページング処理を作りにくくなります。
また、HTTPステータスコードとエラー形式も重要です。認証切れ、権限不足、バリデーションエラー、サーバー障害がすべて同じ形式で返ってくると、AxiosのインターセプトやTanStack Queryの再試行条件を適切に設定できません。
特に再試行との相性が悪いのは、次のようなエラーです。
- 入力値の検証に失敗したエラー
- 認証トークンが無効になったエラー
- 権限がないため拒否されたエラー
- 存在しないリソースを指定したエラー
これらは同じリクエストを繰り返しても成功しない可能性が高いため、すべてを自動再試行させるのではなく、エラーの種類に応じて制御してみましょう。
WordPressのREST APIを利用する場合も、投稿一覧、ターム一覧、メディア情報など、データの更新頻度に差があります。頻繁に変わらないターム情報は長めに保持し、投稿一覧は公開や編集のタイミングに応じて再取得するなど、データ単位で設定を分けると通信量と鮮度のバランスを取りやすくなります。
迷ったときは「通信回数」より「状態の責務」で考える
TanStack Queryを導入する理由として、通信回数の削減だけを考えると、判断を誤ることがあります。キャッシュを使えば通信が減る場合はありますが、常に通信を減らすことが正解とは限りません。
たとえば在庫数や通知件数など、最新状態が重要なデータでは、キャッシュを長く保持しすぎるとユーザーへ古い情報を見せることになります。一方で、頻繁に変化しないマスターデータを毎回取得すると、APIとブラウザの両方に不要な負荷がかかります。
見るべきなのは、次のような責務です。
- APIから取得したデータを、複数の場所で共有する必要があるか
- データが古くても許容できる時間はどの程度か
- 画面へ戻ったときに再検証したいか
- 更新処理のあと、どの画面を同期させる必要があるか
- 通信エラー時に再試行すべきか
- 自作フックの状態管理が、すでに重複していないか
- チーム内でクエリキーやキャッシュ更新のルールを維持できるか
この視点で見ると、自作Axiosフックは「小さいから正しい」、TanStack Queryは「大きいから正しい」という単純な話ではありません。要件に対して、どの仕組みが最も説明しやすく、あとから同じ判断を再現できるかが大切です。
まとめ:Axiosを捨てるのではなく、役割を分けて導入する
TanStack Queryと自作Axiosフックを比較するとき、Axiosを通信層、TanStack Queryをサーバー状態の管理層として分けて考えると、選択肢が整理されます。
自作Axiosフックは、単一画面で一度だけデータを取得する処理や、キャッシュが不要な単発処理では、軽量で理解しやすい方法です。一方、同じデータを複数画面で共有する、取得結果をキャッシュする、ウィンドウフォーカス時に再検証する、更新後に関連データを同期するといった要件が増えた場合は、TanStack Queryの仕組みが有効になります。
導入時には、まずAxiosの通信設定を整理し、次にクエリキーを設計し、その後で自作フックを段階的に移行してみましょう。staleTimeとgcTimeの役割を分け、取得処理と更新処理を同じものとして扱わないようにすると、キャッシュの挙動を説明しやすくなります。
特定のバージョンに依存したサンプルを使うときは、TanStack Query v5のAPIや設定名と一致しているかも確認してください。とくにcacheTimeからgcTimeへの変更や、古いフックAPIの書き方は、移行時のエラーにつながりやすい部分です。
まずは、同じAPIを複数のコンポーネントが呼び出している画面を一つ選び、そこからクエリキーとキャッシュの流れを整えてみましょう。仕組みを理解したうえで小さく移行すれば、TanStack QueryはAxiosを置き換えるものではなく、今ある通信処理を安定して育てるための土台として活用できます。