🐷

TanStack Routerを使ってみた

2024/11/26に公開

はじめに

最近よくハッカソンでは、フロントエンドとバックエンドを分けて実装します
そしてフロントには React を採用しますが、フレームワークで Next.js を使うことがあります

正直なんとなくで使っていて、確実に Next.js な必要がないと思うことばかりです

Vite + React で十分ではあるのですが、ルーティングをどうしようということでファイルベースルーティングができるTanStack Routerを試してみようと思います!

TanStack Router とは

React のルーティングを行うためのライブラリです
https://tanstack.com/router/latest

使ってみる

公式の Quick Start に沿ってやってみます
https://tanstack.com/router/latest/docs/framework/react/quick-start

プロジェクトを作る

TanStack Router はライブラリなのでもちろん既にある Vite のプロジェクトにインストールしてもいいのですが、今回は最初からということで、TanStack Router が元々入ったプロジェクトを作ります
pnpm を利用していきます

pnpm create @tanstack/router

? Enter the project name (my-router-app) ... プロジェクト名
? Select a bundler (Use arrow keys)
❯ vite
  webpack
  rspack
? Select an IDE (Use arrow keys)
❯ vscode
  cursor
  other
? Open the generated project using vscode after creation? (Y/n) ... Y

よくあるフレームワークのセットアップみたいな感じでいくつか質問があります
IDE について聞かれるのは初めて見ました
そして最後の質問に Yes で答えると、プロジェクト作成後にそのまま作ったプロジェクトを開いてくれます

pnpm run devで実行してみるとこのような画面になります

ダークモードなのでわかりにくいですが、上の部分がナビゲーションで下がコンテンツという構成です
About をクリックすると、localhost:3001/aboutに飛んで以下のように表示が変わります

コードについて

ここまでプロジェクトを作成して触ってみましたが、これらがどこにどのように記述されているのかを見てみます

まずディレクトリ構成としてはこのようになっています

├── index.html
├── package.json
├── pnpm-lock.yaml
├── src
│   ├── main.tsx
│   ├── routeTree.gen.ts
│   └── routes
│       ├── __root.tsx
│       ├── about.tsx
│       ├── index.tsx
├── tsconfig.json
└── vite.config.ts

routes以下がページとして出るところですね
__root.tsxはページじゃなくて全体的なレイアウトで、最初はLinkOutletが入ってます

__root.tsx
function RootComponent() {
  return (
    <>
      <div className="p-2 flex gap-2 text-lg">
        <Link
          to="/"
          activeProps={{
            className: "font-bold",
          }}
          activeOptions={{ exact: true }}
        >
          Home
        </Link>
        <Link
          to="/about"
          activeProps={{
            className: "font-bold",
          }}
        >
          About
        </Link>
      </div>
      <hr />
      <Outlet />
      <TanStackRouterDevtools position="bottom-right" />
    </>
  );
}

Outletにはそれぞれのページの内容が表示されて、TanStackRouterDevtoolsは TanStack Router が提供している開発者ツールです

ページを増やしてみる

ファイルベースのルーティングなので、ファイルを増やしてみましょう!
routesの中にtodo.tsxというファイルを作ります

するとファイルを作っただけで、このようなコードが生成されました!
(pnpm run devでサーバー立ち上げている状態)

todo.tsx
import * as React from "react";
import { createFileRoute } from "@tanstack/react-router";

export const Route = createFileRoute("/todo")({
  component: RouteComponent,
});

function RouteComponent() {
  return <div>Hello "/todo"!</div>;
}

ではlocalhost:3001/todoにアクセスしてみます

ナビゲーションの部分は変わらず、下の部分が Hello "/todo"!に変わりました!

ネストしたルーティング

さらにネストしたルーティングを作るには、Next.js のような Directory Routes と、Remix のような Flat Routes の 2 種類があります

まさかの組み合わせることもできるそうです!

https://tanstack.com/router/latest/docs/framework/react/guide/file-based-routing

今回は自分に馴染みのある Directory Routes でやってみます

まずroutespostsというディレクトリを増やします
そして、postsの中にindex.tsxを作成すると、これがlocalhost:3001/postsになりますね

現状の構造
├── routes
│   ├── __root.tsx
│   ├── about.tsx
│   ├── index.tsx
│   ├── todo.tsx
│   └── posts
│       ├── index.tsx # localhost:3001/posts

ではpostIdのような可変のパスの場合はどうするでしょう
Next.js の場合は:をつけますが、TanStack Router の場合は$というプレフィックスをつけるそうです

postsの中に$postIdというファイルを作ります

posts/$postId.tsx
import * as React from 'react'
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/posts/$postId')({
  component: RouteComponent,
})

function RouteComponent() {
  return <div>Hello "/posts/$postId"!</div>
}

これでlocalhost:3001/posts/1などにアクセスできます
でも中身は他のファイルとそんなに変わってるようには見えませんね

現状の構造
├── routes
│   ├── __root.tsx
│   ├── about.tsx
│   ├── index.tsx
│   ├── todo.tsx
│   └── posts
│       ├── index.tsx # localhost:3001/posts
│       ├── $postId.tsx # localhost:3001/posts/1 など

ではコンポーネントでpostIdを取得してみます

posts/$postId.tsx
import * as React from "react";
import { createFileRoute } from "@tanstack/react-router";

export const Route = createFileRoute("/posts/$postId")({
  component: RouteComponent,
});

function RouteComponent() {
  const { postId } = Route.useParams();
  return <div>Post {postId}</div>;
}

Route のuseParamsフックを使用すると URL から postId にアクセスできるようですね

まとめ

今回は簡単に TanStack Router を試してみました!
まだloader関数についてなど知らないことが多いので、学びつつ実際に開発に使ってみようと思います

あと、TanStack Query とも相性が良いようなので組み合わせて使ってみたいです

Discussion