TanStack Routerをマスターする:React開発者のための究極のType-safeルーティング術

Development tutorial - IT technology blog
Development tutorial - IT technology blog

ケアレスミスによる404の悪夢に終止符を

navigate('/users/profile') で ‘s’ を一文字打ち間違えただけで、デバッグに何時間も費やしたことはありませんか? 従来のReact Routerでは、TypeScriptはURL文字列に対して完全に「無力」です。その結果、開発中に警告が出ることもなく、アプリがクラッシュしたり、ユーザーが予期せぬ404ページに飛ばされたりしてしまいます。

私が参加した150以上のルートを持つ実際のプロジェクトでは、React RouterからTanStack Routerへリファクタリングしたことで, ナビゲーション関連のバグが80%削減されました。記憶に頼るのではなく、IDEが1文字ずつ補完してくれます。ルート名を変更すれば、コードベース全体が即座にエラーを表示します。これこそが、プロフェッショナルな開発者が必要とする安心感です。

徹底比較:React Router vs TanStack Router

なぜReactコミュニティでこれほどまでにTanStack Routerが話題になっているのでしょうか? アプローチの根本的な違いを見てみましょう。

React Routerの限界

コンポーネントベースの考え方(<Route><Routes> で囲む)はかつて非常に成功しましたが、プロジェクトが大規模になるにつれて欠点が目立つようになりました。特にSearch Params(?page=1&sort=desc など)の管理は非常に苦痛です。URLから手動で文字列を取得し、型をキャストし、そのデータがnullや不正な形式でないことを祈るしかありませんでした。

TanStack Routerのモダンな考え方

TanStack Routerは完全なType-safetyを最優先します。最初から厳格なルートツリー構造を定義することを求められます。<Link> コンポーネントを使用する際、Ctrl + Space を押すだけで、IDEが100%正確なルートリストを表示します。タイポや推測に頼る必要はもうありません。

TanStack Routerがルーティングの「新王者」となった理由

私がTanner Linsley氏(TanStack Queryの生みの親)のエコシステムに完全に移行した理由は、以下の3つの大きなメリットがあるからです。

  • 包括的なTypeScript制御: パス、パラメータからSearch Paramsに至るまで、すべてが明確なデータ型で定義されます。
  • プロフェッショナルなSearch Paramsバリデーション: Zodを使用してURLに型を強制できます。例えば、page パラメータを必須の数値とし、デフォルト値を1に設定できます。ユーザーが意図的に page=abc と入力した場合、ルーターが自動的に処理するか、安全な値に戻してくれます。
  • 非常にスムーズなデータローディング: TanStack Routerは「ウォーターフォール」(コンポーネントのレンダリングが終わってからデータをフェッチする状態)を解消します。ルートのロード中にデータを並列で読み込むため、待ち時間(LCP)を大幅に短縮できます。

実践的な導入:理論から実装まで

それでは、大規模プロジェクトにも耐えうる標準的なルーティング構造を構築してみましょう。

1. プロジェクトの初期化

ターミナルを開き、プロジェクトにライブラリを追加します:

npm install @tanstack/react-router zod
# Zodを使うことで、Search Paramsのバリデーションが非常に強力になります

2. ルートツリーの構築

src/routes/root.tsx ファイルを作成します。これがアプリケーション全体の骨格となります。

import { createRootRoute, Link, Outlet } from '@tanstack/react-router';
import { TanStackRouterDevtools } from '@tanstack/router-devtools';

export const routeTree = createRootRoute({
  component: () => (
    <div className="min-h-screen bg-gray-50">
      <nav className="p-4 border-b bg-white flex gap-4">
        <Link to="/" className="[&.active]:text-blue-600 [&.active]:font-bold">ホーム</Link>
        <Link to="/products" className="[&.active]:text-blue-600 [&.active]:font-bold">商品</Link>
      </nav>
      <main className="p-6">
        <Outlet />
      </main>
      <TanStackRouterDevtools />
    </div>
  ),
});

3. プロのようにSearch Paramsを管理する

商品一覧ページを作成していると想像してみてください。Zodとの組み合わせにより、pageq(検索クエリ)によるフィルタリングがかつてないほど簡単になります。

import { createRoute } from '@tanstack/react-router';
import { z } from 'zod';

const productSearchSchema = z.object({
  page: z.number().fallback(1),
  q: z.string().optional(),
});

export const productsRoute = createRoute({
  getParentRoute: () => routeTree,
  path: 'products',
  validateSearch: (search) => productSearchSchema.parse(search),
  component: ProductsPage,
});

function ProductsPage() {
  const { page, q } = productsRoute.useSearch();
  return (
    <div>
      <h1>検索結果: {q || 'すべて'}</h1>
      <p>現在のページ: {page}</p>
    </div>
  );
}

実装における「痛恨の教訓」

errorComponent を決して無視しないでください。実際の環境では、APIはいつでもダウンする可能性があります。ユーザーに冷たい真っ白な画面を見せるのではなく、そのルートで適切なエラー通知UIを設計しましょう。これにより、ユーザーエクスペリエンス(UX)が大幅に向上します。

大規模プロジェクト向けのちょっとしたコツ:一日ですべてを書き換える必要はありません。まずは新しいモジュールにTanStack Routerを適用してみてください。その便利さを実感すれば、残りの部分の移行は苦痛ではなく、ワクワクするものになるはずです。

Lời kết

最初こそTypeScriptの設定などが少し手間に感じるかもしれませんが、TanStack Routerは間違いなく投資に値するものです。コードがよりクリーンになるだけでなく、数多くのつまらない実行時エラーからあなたを守ってくれます。保守性が高く持続可能なReactアプリを構築したいなら、ぜひ今日から導入してみてください。

Share: