TanStack Routerを使ってみた
はじめに
最近よくハッカソンでは、フロントエンドとバックエンドを分けて実装します
そしてフロントには React を採用しますが、フレームワークで Next.js を使うことがあります
正直なんとなくで使っていて、確実に Next.js な必要がないと思うことばかりです
Vite + React で十分ではあるのですが、ルーティングをどうしようということでファイルベースルーティングができるTanStack Router
を試してみようと思います!
TanStack Router とは
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
はページじゃなくて全体的なレイアウトで、最初はLink
とOutlet
が入ってます
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
でサーバー立ち上げている状態)
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 種類があります
まさかの組み合わせることもできるそうです!
今回は自分に馴染みのある Directory Routes でやってみます
まずroutes
にposts
というディレクトリを増やします
そして、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
というファイルを作ります
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
を取得してみます
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