【脱react-router-dom】React で 超簡単 File-based ルーティング！！！【TanStack Router】

# File-based ルーティングの開発体験を紹介
File-based ルーティングの世界では、こんな感じの開発が行えます。

![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/4a306cb4-ce61-72c3-d8b9-e1e56ad8e565.gif)

少しでも興味をもってもらえたでしょうか？

この記事では以下の構成でFile-based ルーティングに入門します

**① File-based ルーティングって？**
**② 実際にReactでFile-based ルーティングしてみる！～with TanStack Router～**
**③ TanStack Router をvitestでテストして、仕組みを理解する（別記事）**

やっていきます！


# ① File-based ルーティングって？
File-based ルーティングについて、少し深掘りしてみます！！

File-based ルーティングとは、jsxファイルのルーティングを、コードでの設定ではなく、
物理的なディレクトリの位置で行おう！という考え方です。

コードベースのルーティングとファイルベースのルーティングを比較して、どんなものかイメージしてみます。

## コードベースのルーティング（React-router-dom）
```route.tsx
    <Router>
      <div>
        <Navbar />
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
          <Route path="/blog" element={<BlogIndex />} />
          <Route path="/blog/:id" element={<BlogPost />} />
        </Routes>
      </div>
    </Router>
```

コードベースルーティングのサンプルです。
なじみのある人も多いのではないでしょうか。

コードベースルーティングは、Reactコンポーネントをpathに紐づけてコード上で設定する方式です。

メリットはいろいろありますが、個人的には以下が特に好みです
- すべてのルートが1つのファイルで管理可能
- ルーティングの全体像が把握しやすい

## ファイルベースのルーティング
```
routes/
├── index.tsx           // → /
├── about.tsx           // → /about
└── blog/
    ├── index.tsx       // → /blog
    └── $id/
         └── index.tsx  // → /blog/:id （動的ルーティング）
```

今回入門するファイルベースルーティングのサンプルです

FWまたはライブラリを使用/インストールするだけで基本的には設定が完了します。

設定ファイルなどの細かな設定・更新は不要で、
コンポーネントファイルを作成すると、そのファイル名やディレクトリが自動的にpathに設定されます。

```routes/index.tsx``` → ```/``` でアクセス可能
```routes/about.tsx``` → ```/about``` でアクセス可能
```routes/blog/index.tsx``` → ```/blog``` でアクセス可能

メリットはいろいろありますが、個人的には以下が特に好みです
- プロジェクト構造が視覚的に理解しやすい
- 設定ファイルの更新が不要

今回はこのファイルベースルーティングを **TanStack Router** というライブラリでReactに実装していきます！！！！！

# ② 実際にReactでFile-based ルーティングしてみる！～with TanStack Router～

テンションを上げるために冒頭のgifを再掲します

![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/4a306cb4-ce61-72c3-d8b9-e1e56ad8e565.gif)

```routes/test/sample.tsx``` → ```/test/sample``` でアクセス可能になっていることが確認できます。

良い感じですね

やっていきましょう！

今回はこんな感じでTanStack Routerを触っていきます
1. vite + React開発環境の作成
1. tanstack routerをインストールする
1. tanstack routerをセットアップする
1. tanstack routerを使ってFile-based ルーティング！！！
1. tanstack routerの凄さ・ありがたさに少し触れる

## vite + React開発環境の作成
tanstack routerはvite環境に対応しているため、素直にviteを使います。

https://ja.vite.dev/guide/#%E6%9C%80%E5%88%9D%E3%81%AE-vite-%E3%83%95%E3%82%9A%E3%83%AD%E3%82%B7%E3%82%99%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8B

```powershell
npm create vite@latest my-tanStack-app -- --template react-ts
```
ドキュメントを参考にプロジェクトを作成します。

```powershell
> npm create vite@latest my-tanStack-app -- --template react-ts
√ Package name: ... my-tanstack-app

Scaffolding project in C:\work\react\my-tanStack-app...

Done. Now run:

  cd my-tanStack-app
  npm install
  npm run dev

```

作成が完了しました。

```powershell
  cd my-tanStack-app
  npm install
```

依存パッケージをインストールします。

```powershell
> npm install

added 192 packages, and audited 193 packages in 49s

41 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
```

開発サーバーを起動して、動作確認します

```powershell
npm run dev
```

```powershell
> npm run dev

> my-tanstack-app@0.0.0 dev
> vite


  VITE v5.4.8  ready in 1209 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help
```

```http://localhost:5173/``` にアクセスします

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/e27713e5-9dca-dc79-8ec1-73aa49dd1e9a.png)

良い感じですね

では早速File-based ルーティングに入門しましょう！！

## tanstack routerをインストールする
### ライブラリ本体をインストールする
ドキュメントを参考にライブラリをインストールしていきます。

https://tanstack.com/router/latest/docs/framework/react/quick-start#scaffolding-your-first-tanstack-router-project

```powershell
npm add -D @tanstack/router-plugin @tanstack/router-devtools @tanstack/react-router
```

<font color="Red">**※ドキュメントには記載がないですが、```@tanstack/react-router``` ライブラリも動作に必要なのでインストールします**</font>

### vite.config.ts にtanstack router用のpluginを追加する
viteではpluginという機能を用いて、ビルド時・ビルド中にファイル生成やコンパイル処理を行うことができます。

tanstack routerはこの仕組みを利用して、動的にファイルの生成や書き換えを行います。
プラグインを有効化しておくと、冒頭のgifのように、自動的にルーティングしてくれるので、有効化します。

```diff_typescript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
+ import { TanStackRouterVite } from '@tanstack/router-plugin/vite'

// https://vitejs.dev/config/
export default defineConfig({
-  plugins: [react()],
+  plugins: [
+    TanStackRouterVite(),
+    react()
+  ],
})
```

pluginsをインポートして、追加する感じですね

```vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { TanStackRouterVite } from '@tanstack/router-plugin/vite'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    TanStackRouterVite(),
    react()
  ],
})
```

完成形も載せておきます

### routesディレクトリ、routes/__root.tsxを準備する
デフォルトでは、tanstack router は ```src/routes``` 配下のファイルを自動的にルーティングしてくれます
まずは ```src/routes``` を作成します。

```powershell
mkdir src/routes
```

また、 ```src/routes``` 配下には、 ```__root.tsx``` というtsxが必要です。
このtsxは、routes配下の全てのルートで適用されるtsxです。
ヘッダーやフッターなどを記載しておくと便利ですね。

まずは作成してみます

```
touch src/routes/__root.tsx
```

中身はからっぽで大丈夫です。

上述した通り、tanstack routerはpluginsを利用して、動的にファイルの生成や書き換えを行います
__root.tsxの中身も初期化してくれるので、 ```npm run dev``` してプラグインを実行します。

```powershell
npm run dev
```

```powershell
> npm run dev

> my-tanstack-app@0.0.0 dev
> vite


♻️  Generating routes...
🟡 Creating C:\work\react\my-tanStack-app\src\routes\__root.tsx
🟡 Updating C:\work\react\my-tanStack-app\src\routeTree.gen.ts
✅ Processed routes in 432ms

  VITE v5.4.8  ready in 3055 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help

```
だーっとログが出て、ローカルサーバーが起動しました。

tanstack router pluginのログに注目してみます

```powershell
♻️  Generating routes...
🟡 Creating C:\work\react\my-tanStack-app\src\routes\__root.tsx
🟡 Updating C:\work\react\my-tanStack-app\src\routeTree.gen.ts
✅ Processed routes in 432ms
```

>🟡 Creating C:\work\react\my-tanStack-app\src\routes\__root.tsx

```__root.tsx``` の初期化をおこなってくれてます。中身を見てみます

```src\routes\__root.tsx
import * as React from 'react'
import { Outlet, createRootRoute } from '@tanstack/react-router'

export const Route = createRootRoute({
  component: () => (
    <React.Fragment>
      <div>Hello "__root"!</div>
      <Outlet />
    </React.Fragment>
  ),
})
```

Outletコンポーネントは子供コンポーネントをレンダリングしてくれるコンポーネントです（超意訳）

https://tanstack.com/router/v1/docs/framework/react/guide/outlets

どのルートでも共通で表示したいもの、実行したい処理を記載することができます。
今回は見出しのみ表示させておきます

```diff_typescript
import * as React from 'react'
import { Outlet, createRootRoute } from '@tanstack/react-router'

export const Route = createRootRoute({
  component: () => (
    <React.Fragment>
-      <div>Hello "__root"!</div>
+     <h1>TanStack Router やってみた</h1>
      <Outlet />
    </React.Fragment>
  ),
})
```

共通のヘッダーやフッターを書きたい場合、
```<Header /><Outlet /><Footer /> ``` とするとよさそうですね

```src\routes\__root.tsx
import * as React from 'react'
import { Outlet, createRootRoute } from '@tanstack/react-router'

export const Route = createRootRoute({
    component: () => (
        <React.Fragment>
            <h1>TanStack Router やってみた</h1>
            <Outlet />
        </React.Fragment>
    ),
})
```

完成形です。

まだ、準備が必要なので準備します。

また、以下のログもとても**大事**なのですが、今解説するとややこしいので、**細かい解説はテストコードを書く時に記載する**ので割愛します！

> 🟡 Updating C:\work\react\my-tanStack-app\src\routeTree.gen.ts

### src/main.tsx を編集する
main.tsxで、tanstack routerをReactアプリ内部で使用するようコードを修正します


https://tanstack.com/router/latest/docs/framework/react/quick-start#srcmaintsx

ここもとても**大事**なのですが、**細かい解説はテストコードを書く時に記載する**ので割愛します！
とりあえずコピペで大丈夫です

```src/main.tsx
import React, { StrictMode } from 'react'
import ReactDOM from 'react-dom/client'
import { RouterProvider, createRouter } from '@tanstack/react-router'

// Import the generated route tree
import { routeTree } from './routeTree.gen'

// Create a new router instance
const router = createRouter({ routeTree })

// Register the router instance for type safety
declare module '@tanstack/react-router' {
  interface Register {
    router: typeof router
  }
}

// Render the app
const rootElement = document.getElementById('root')!
if (!rootElement.innerHTML) {
  const root = ReactDOM.createRoot(rootElement)
  root.render(
    <StrictMode>
      <RouterProvider router={router} />
    </StrictMode>,
  )
}
```

main.tsxを保存すると、viteがファイルの変更を検知し、
自動でpluginを実行してくれます。以下のログが表示されれば幸せです

```powershell
10:41:01 [vite] page reload src/main.tsx
10:41:02 [vite] ✨ new dependencies optimized: @tanstack/react-router
10:41:02 [vite] ✨ optimized dependencies changed. reloading
```

>10:41:02 [vite] ✨ new dependencies optimized: @tanstack/react-router
10:41:02 [vite] ✨ optimized dependencies changed. reloading

なんか成功っぽいログが出てます。いいですね

1. [✓] vite + React開発環境の作成
1. [✓] tanstack routerをインストールする
1. [✓] tanstack routerをセットアップする
1. [] tanstack routerを使ってFile-based ルーティング！！！
1. [] tanstack routerの凄さ・ありがたさに少し触れる

ここまで長かった・・・


### tanstack routerを使ってFile-based ルーティング！！！

起動している ```http://localhost:5173/```を確認します。

![cap1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/8bc6ed25-4570-d5ac-49ff-d8806cfc455c.png)

```__root.tsx``` で設定した見出しが表示されていますね！
ただ、 ```Not Found``` の表示も・・・

ただ、まだ何もファイルを配置していないので、ファイルベースルーティング的には正しい挙動ですね。

色々ファイルを置いて試していきます。

ここではTanStack Routerの主要なルーティングルールのうち、３つを確認します

### ルール ① index.tsxはディレクトリパスにルーティングされる
```routes/index.tsx``` を作成します。
routesはrootディレクトリなので、このindex.tsxは「/」で表示されるはずです。

```
touch src/routes/index.tsx
```

ファイルを作成します
すると、再度viteがファイルの変更を検知し、tanstack routerのpluginを実行します

```powershell
♻️  Regenerating routes...
🟡 Updating C:\work\react\my-tanStack-app\src\routes\index.tsx
🟡 Updating C:\work\react\my-tanStack-app\src\routeTree.gen.ts
✅ Processed route in 139ms
10:50:11 [vite] page reload src/routeTree.gen.ts
```

それっぽいログが出ました！

>🟡 Updating C:\work\react\my-tanStack-app\src\routes\index.tsx
🟡 Updating C:\work\react\my-tanStack-app\src\routeTree.gen.ts

>🟡 Updating C:\work\react\my-tanStack-app\src\routes\index.tsx

どんな感じか見に行きましょう

```src\routes\index.tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/')({
  component: () => <div>Hello /!</div>,
})
```

色々記載されてますね。大事なところだけ確認します

**大事なところ①：ルートの作成**
```
export const Route = createFileRoute('/')({
```

自動生成でルートへの登録が行われている部分です
いや、結局コードベースで設定しとんかーい、というツッコミを感じる方もいるかもしれませんが、
この記述はpluginが行ってくれます。また、引数を勝手に変えると怒られます。

![cap2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/813faa74-4b1f-4c2a-bf63-e6ed957dbd67.png)

型で守られている + 自動生成で実質File-based ルーティングな感じです。
微妙に感じる方もいるかもしれませんが、このアーキテクチャのおかげで、さまざまなメリットが生まれます。この後確認します！！！

**大事なところ②：コンポーネントの登録**
```
  component: () => <div>Hello /!</div>,
```
```component：``` に対して、JSXを返却する関数を割り当てています。

以下のような書き方が可能です

- 即時関数としてその場でコンポーネントを定義するパターン（自動生成されたやつはこれ）
```src\routes\index.tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/')({
  component: () => <div>Hello /!</div>,
})
```

- ファイル内でコンポーネントを定義するパターン
```src\routes\index.tsx
import { createFileRoute } from '@tanstack/react-router'

// 先に変数として定義する必要がある（それはそう）
const jsx = () => {
  return <div>Hello /!</div>
}

export const Route = createFileRoute('/')({
  component: jsx
})
```

- ファイル外のコンポーネントを引き渡すパターン

```src\components\Message.tsx
export const Message = () => {
    return <div>Hello /!</div>
}
```

```src\routes\index.tsx
import { createFileRoute } from '@tanstack/react-router'
import { Message } from '../components/Message'

export const Route = createFileRoute('/')({
  component: () => <Message />
})
```

### ルール ② route.tsxはディレクトリパス、ディレクトリ配下全てのパスにルーティングされる
```route.tsx``` も ```index.tsx``` と同様にディレクトリパスにルーティングされます。
また、**ディレクトリ配下全てのパスにもルーティングされます**。

```
mkdir src/routes/sample/
touch src/routes/sample/route.tsx
```

ディレクトリ、ファイルを作成します。

```powershell
♻️  Regenerating routes...
🟡 Updating C:\work\react\my-tanStack-app\src\routes\sample\route.tsx
🟡 Updating C:\work\react\my-tanStack-app\src\routeTree.gen.ts
✅ Processed routes in 162ms
```

pluginが実行されます。Updateされたファイルを確認します

```src\routes\sample\route.tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/sample')({
  component: () => <div>Hello /sample!</div>,
})
```

```src\routes\sample\route.tsx
export const Route = createFileRoute('/sample')({
```

```/sample``` にルーティングされていることが確認できます。

![cap3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/d5510827-d67a-39df-e5d6-d78b0cffbf54.png)

いいかんじですね

ディレクトリ配下全てにルーティングされることも確認します。

```
mkdir src/routes/sample/child
touch src/routes/sample/child/index.tsx
```

```http://localhost:5173/sample/child``` にアクセスしてみます。

![cap7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/b1943746-a902-447e-4221-389ba76a11ff.png)

```Hello /sample/test!``` ではなく、```Hello /sample!``` が表示されています。

ディレクトリ配下全てにルーティングされることが確認できました。
```src/routes/sample/child/index.tsx``` の内容を表示するには、sample 側で ```<Outlet />``` を使用する必要があります。

```src\routes\sample\route.tsx
import { createFileRoute, Outlet } from '@tanstack/react-router'

export const Route = createFileRoute('/sample')({
    component: () => <><div>Hello /sample</div><Outlet /></>,
})
```

![8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/2784958c-7bc7-a59b-ed16-c11d6bab88ee.png)

このように、 ```route.tsx``` はディレクトリ配下全てのルートで使用されることが確認できました。

### ルール ③ index/route以外のXXX.tsxは、ディレクトリ/XXXパスにルーティングされる
ちょっとわかりづらいですが、以下のようにルーティングされます。

```routes/test.tsx → /test にルーティング```
```routes/sample/test.tsx → /sample/test にルーティング```

ややこしいですが、```route.tsx``` と ```index.tsx```  が同時に存在するとバグるのと同じ理由で、
**```routes/test.tsx``` が存在する場合、 ```routes/test/index.tsx``` が存在すると、ルーティングが被ってバグります**

以上がTanstack Routerの基本的なルーティングルールです。

### では、index.tsxとroute.tsxとXXX.tsxはどう使い分ける？個人的な結論
それぞれの違いは下記記事がとても分かりやすいです。

https://zenn.dev/nbstsh/scraps/ca36d074963335

結論：
- **```route.tsx```と```XXX.tsx```はレイアウトコンポーネントとして使える**
- **```index.tsx``` はディレクトリのルートコンポーネントとしてのみ作用する**

これらの特徴を鑑みて、以下の結論にしました！
① 基本的に ```index.tsx``` でパスに対するコンポーネントを作成する
② ```route.tsx``` は特定パス配下で部分的に共通のレイアウトを使用したい場合に作成する（また、細かいパス管理は避ける）
③ どちらの役割なのかわからず、複雑になるため、```XXX.tsx``` は基本的に使用しない

```diff
routes/
├── index.tsx           // → /
-├── about.tsx           // → /about
+└── about/
+      └── index.tsx    // → /about
└── blog/
+   ├── route.tsx       // <Outlet /> を使用し、/blog と /blog/:id に共通レイアウトを提供
    ├── index.tsx       // → /blog
    └── $id/
         └── index.tsx  // → /blog/:id （動的ルーティング）
```

図にするとこんな感じです！

## tanstack routerの凄さ・ありがたさに少し触れる
File-based ルーティングのためだけなら、tanstack router以外にも選択肢があるので、
tanstack router の素晴らしい機能も体験してみます。

以下で紹介するtanstack router の素晴らしさは、
File-based ルーティングのすばらしさと直接関係しないものもあるので、
整理する際は注意してもらえればと思います！

### **素晴らしく型安全なルーティング**
プレーンなreact-router-domだと、以下のようなコードがエラーとならず実行できてしまいます。

```src/tekitou.tsx
import type { MouseEvent } from "react";

import { useNavigate } from 'react-router-dom';

export const SubmitButton = () => {

    const navigate = useNavigate();

    const handleClick = (e: MouseEvent<HTMLButtonElement>) => {
        e.preventDefault();
        navigate("/sonzaishinai_path", {
            state: {
                test: 1234,
                wakaran: 5678,
                kore_watashite_iino: "dame",
            }
        });
    };

    return (
        <button onClick={handleClick}>submit!</button>
    );
};
```

主な課題は2つあります。

1. navigate先は全てのstringが許可されている

```src/tekitou.tsx
        navigate("/sonzaishinai_path", {
```

許されちゃってますね

2.stateの型は特に設定されていない

```src/tekitou.tsx
        navigate("/sonzaishinai_path", {
            state: {
                test: 1234,
                wakaran: 5678,
                kore_watashite_iino: "dame",
            }
        });
```
許されちゃってますね

では、Tanstack Router ではどうでしょう？確認してみます

#### テスト用コンポーネント準備
```src\components\Message.tsx
interface MessageProps {
    message: string;
    year: number;
}

export const Message: React.FC<MessageProps> = ({ message, year }) => {
    return <div>{message} in {year}</div>
}
```

viewっぽい雰囲気のコンポーネントです。
```message``` と ```year``` を受け取って、div内で表示します。
routes配下のコンポーネントが、このコンポーネントを表示します。

```src\routes\sample\route.tsx
import { createFileRoute } from '@tanstack/react-router'
import { Message } from '../../components/Message'

interface MessageProps {
  message: string;
  year: number;
}

const Sample = () => {
  const params = Route.useSearch()
  return <Message message={params.message} year={params.year} />
}

export const Route = createFileRoute('/sample')({
  validateSearch: (search: Record<string, unknown>): MessageProps => {
    return {
      message: String(search?.message ?? "not found"),
      year: Number(search?.year ?? 9999)
    }
  },
  component: Sample
})
```

```src\routes\sample\route.tsx``` を、```Messafe.tsx``` をレンダリングするよう修正しました。
重要なところが2点あるので、解説します。

**① validateSearch でstateをURLクエリパラメータとして表現**

```src\routes\sample\route.tsx
  validateSearch: (search: Record<string, unknown>): MessageProps => {
    return {
      message: String(search?.message ?? "not found"),
      year: Number(search?.year ?? 9999)
    }
  },
```

Tanstack Router では、localなstateはURLクエリパラメータを介してやり取りすることが推奨されています。
（また、DBの情報などの、サーバーサイドのstateは別のTanstack Queryというライブラリで管理することが推奨されています。こっちも記事書きたい）

クエリパラメータとしてstateを引き渡すために、この ```validateSearch``` を利用することができます。

https://tanstack.com/router/latest/docs/framework/react/guide/search-params

```validateSearch``` の名前の通り、高度なvalidateも実装できるのですが、いったん今回はスコープ外として、さっくり解説します。

```src\routes\sample\route.tsx
  validateSearch: (search: Record<string, unknown>): MessageProps => {
```

serchパラメーターを受け取って、その中からどういったオブジェクトを取得するか？を記載しています。
serchパラメーターはユーザーまたは遷移元が任意の値を付与できるので、```search: Record<string, unknown>``` となっています。

```src\routes\sample\route.tsx
    return {
      message: String(search?.message ?? "not found"),
      year: Number(search?.year ?? 9999)
    }
  },
```

受け取ったserchパラメーターを整形し、Messageコンポーネントが必要なpropsの型のオブジェクトを返却します。
今回はserchパラメーターにmessageとyearがない場合適当な値を代入し、エラーをハンドリングしています。

**② useSearch関数でURLクエリパラメータを取得する**

```src\routes\sample\route.tsx
  const params = Route.useSearch()
```

Routeから、整形されたserchパラメーターを取得しています。
paramsの型は、Routeの ```validateSearch``` の戻り値なので、ここでは ```{ message: string; year: number; }``` となります。

![cap4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/2b72bd7a-3ea2-fa57-aa83-28a07e15efcb.png)

型安全ですね～。

長くなりましたが、呼び出される側の準備はこんな感じです。

では、このルートへ、useNavigate関数などで移動してみます。

#### useNavigate関数
tanstack routerにも useNavigate関数が用意されています。

https://tanstack.com/router/latest/docs/framework/react/guide/navigation#usenavigate

実装してみるとこんな感じになります

![navigate.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/5197e88e-b804-ee88-cf40-68c57644931b.gif)


どうですか？
```path``` も ```state``` も、なにもかも型安全なことが分かったのではないでしょうか？！

```src\components\Button.tsx
import type { MouseEvent } from "react";

import { useNavigate } from '@tanstack/react-router';

export const SubmitButton = () => {

    const navigate = useNavigate();

    const handleClick = (e: MouseEvent<HTMLButtonElement>) => {
        e.preventDefault();
        navigate({ to: "/sample", search: { message: "type safe!", year: 3150 } });
    };

    return (
        <button onClick={handleClick}>submit!</button>
    );
};
```

#### Linkコンポーネント
Tanstack Routerはリンクコンポーネントも提供してくれています。

https://tanstack.com/router/latest/docs/framework/react/api/router/linkComponent

navigate関数と同様、型安全が保障されています。

![cap5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/1fbe5d1d-59e3-9977-eae1-ebec05638d18.png)

![cap6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/ed8e28e6-cca1-8bd9-b870-7b7245aeb58f.png)

```src\components\MoveLink.tsx
import { Link } from "@tanstack/react-router"

export const MoveLink = () => {
    return <Link to={"/sample"} search={{ message: "reiwa", year: 2019 }} />
}
```

どうだったでしょうか？
File-based ルーティングもできるし、型安全な開発も加速するし、最高！！となったでしょうか。

TanStack Routerには他にもloaderやlazyなど色んな機能がありますが、いったんここでは触れまないでおこうと思います！。

https://tanstack.com/router/latest/docs/framework/react/overview

# 終わりに
今回はTanStack Routerを軽く使ってみました。
テストコードを書くとライブラリがより深く理解できるので、後日テスト編も記事にしようと思います。