Remix v2からReact Router v7への移行検討
2024年11月22日にReact Router v7のStable Releaseが発表されました。
発表内容にもあるようにRemix v2からReact Router v7への移行を推奨しており公式ドキュメントでもRemixからのUpgrading guideが公開されています。
この記事では現行のRemix v2のコードをReact Router v7に移行するかの判断材料をまとめます。
移行の背景
2024年5月にRemix公式からRemixをReact Routerに統合するというアナウンスがありました。
重要なポイント
- Remix v3としてリリース予定されていたものはReact Router v7としてリリースする
-
@remix-run/*
をreact-router
に移行(依存関係、Importの移行) - React Server Component(RSC)の導入計画
Remix v2から見たReact Router v7の変更点
react-router CHANGELOG.md v7.0.0
※主にRemix v2との差分を調査するためReact Router v6からの差分については触れません。
- React 18->19の移行
- Update dependencies
- ルーティング定義
- Typesafety improvements
React 18->19の移行
Remixが発表している記事によるとReact 19へ移行するにはReact Router v7が前提となるため、Remix v2ユーザーでReact 19を使いたい場合、React Router v7への移行を検討する必要があります。
React 19の中でもReact Server Component(RSC)は大きなアーキテクチャ変更を見通しているようで、今回の移行を終えた後フルスクラッチでRSC対応のバージョンをリリースする方針があるようです。
もしRSCの導入を目的としている場合、次回のリアーキテクチャを待って移行する選択肢もあるかと考えています。
しかし、React 19から利用可能となるReact CompilerはReactの再レンダリングを効率化するuseMemo
、useCallback
などが不要になるパフォーマンス改善が行われることもあり、React 19を採用するために今回の移行をせざる追えない事例が増えることを想定しています。
Update dependencies
Remixで提供していたAPIは全てreact-routerからimportする形になります。
-import { redirect } from "@remix-run/node";
+import { redirect } from "react-router";
また、以下のAPIは削除されます
- json
- defer
- unstable_composeUploadHandlers
- unstable_createMemoryUploadHandler
- unstable_parseMultipartFormData
RemixのloaderやactionのResponseでjsonがよく利用されていましたが今回から削除されるようです。
jsonではなく通常のオブジェクトを返却するだけでよくなりました。
-import { json } from "@remix-run/node";
export async function loader({}: LoaderFunctionArgs) {
let tasks = await fetchTasks();
- return json(tasks);
+ return tasks;
}
ルーティング定義
React Router v7では基本的にConfigベースでルート設定を行います。
app/routes.ts
に全てのroute設定を配置する事になり以下の例のようにLayoutの定義やDynamic segmentsも対応しています。
import {
type RouteConfig,
route,
index,
layout,
} from "@react-router/dev/routes";
export const routes: RouteConfig = [
index("./home.tsx"),
route("about", "./about.tsx"),
layout("./auth/layout.tsx", [
route("login", "./auth/login.tsx"),
route("register", "./auth/register.tsx"),
]),
route("concerts", [
index("./concerts/home.tsx"),
route(":city", "./concerts/city.tsx"),
route("trending", "./concerts/trending.tsx"),
]),
];
Remixユーザー向けに元々のファイルベースrouting方法も残されています。
routes.ts
で@react-router/fs-routes
を利用することで既存のファイル構造を維持できるようです。
import { type RouteConfig, route } from "@react-router/dev/routes";
import { flatRoutes } from "@react-router/fs-routes";
export const routes: RouteConfig = [
// Example config-based route:
route("/hello", "./routes/hello.tsx"),
// File system routes scoped to a different directory:
...(await flatRoutes({
rootDirectory: "fs-routes",
})),
];
Typesafety improvements
今回から追加された機能でroutes.ts
に定義したルート情報から各ルートの型ファイルが自動生成されます。
以下のようにroutes.ts
で定義した動的URLに対応する形で自動的に型定義が生成されることで、自前で型定義を作成する必要がなくなります。
import {
type RouteConfig,
route,
} from "@react-router/dev/routes";
export default [
route("products/:id", "./routes/product.tsx"),
] satisfies RouteConfig;
import type { Route } from "./+types/product";
// types generated for this route 👆
export function loader({ params }: Route.LoaderArgs) {
// 👆 { id: string }
return { planet: `world #${params.id}` };
}
export default function Component({
loaderData, // 👈 { planet: string }
}: Route.ComponentProps) {
return <h1>Hello, {loaderData.planet}!</h1>;
}
移行するかの判断
現時点ではRemixが推奨しているようにReact 19を利用したい場合、React Router v7に移行する方が長期的には良いかと考えています。
特に最新のReactをサポートする必要がなければ既存のRemix v1,v2を維持しつつ今後RSCに対応した大幅アップデート後のタイミングで移植を検討する方法もありかと思います。
実際にRemix v2からReact Router v7への移行作業を行いましたが、既存コードに対して自動的にコード修正してくれるcodemodが利用できたこともあり想定よりも楽に移行できました。
公式のUpgrading guideで問題なく移行できました。
Discussion