React Router v7 の歩き方 - Declarative / Data / Framework の3モードと Remix 統合後の姿

React Router v7 の歩き方 - Declarative / Data / Framework の3モードと Remix 統合後の姿

作成日:
更新日:

「React Router って、ただの URL とコンポーネントの対応づけでしょ?」——そう思っている人ほど、React Router v7 を見ると驚くはずです。v7 は、単なるルーターからローダー・アクションを持つデータ層、さらにはSSR まで含むフルスタックのフレームワークまで、段階的に姿を変えられる作りになりました。

その鍵が 3つのモード(Declarative / Data / Framework)です。この記事では、各モードが何を足すのか、Remix が React Router v7 に統合された経緯、そして Next.js 以外の選択肢としてどう位置づけるかを整理します。

3つのモード: 必要なだけ機能を足す

React Router v7 は、同じライブラリでありながら3段階の使い方を選べます。下にいくほど機能が増えます。

モード何ができるか主な API
DeclarativeURL とコンポーネントの対応、ナビゲーション<BrowserRouter><Link>useNavigateuseLocation
Data+データ読み込み・更新・保留状態createBrowserRouterloaderactionuseFetcher
Framework+Vite プラグインで SSR・型安全・コード分割@react-router/dev、ファイルベースルート、型付き Route Module

1. Declarative モード(一番素朴)

従来イメージどおりの「ルーター」です。URL に応じてコンポーネントを出し、リンクで遷移する。

Declarative モード
import { BrowserRouter } from 'react-router';
 
ReactDOM.createRoot(root).render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
);

<Link>useNavigateuseLocation といった、おなじみの API でアクティブ状態やナビゲーションを扱います。

2. Data モード(データ駆動)

ここからが v7 の本領です。ルート設定を React のレンダリングの外に出すことで、データの読み込み(loader)・更新(action)・保留状態などを扱えるようになります。

Data モード
import { createBrowserRouter, RouterProvider } from 'react-router';
 
const router = createBrowserRouter([
  {
    path: '/',
    Component: Root,
    loader: loadRootData,
  },
]);
 
ReactDOM.createRoot(root).render(<RouterProvider router={router} />);

「コンポーネントの中で useEffect でデータを取る」のではなく、ルートに紐づいた loader がレンダリング前にデータを用意する——この発想の転換が肝です(useEffect の事故を減らす話は React useEffect 完全ガイドも参照)。

3. Framework モード(フルスタック)

最上位が Framework モードです。Data モードを @react-router/dev の Vite プラグインでラップし、フルスタックの体験を足します。

  • 型安全な href と Route Module API
  • 賢いコード分割
  • SPA / SSR / 静的レンダリングの各戦略

ルートはファイルベースで定義し、パラメータまで型が付きます。

Framework モード: ルート定義
import { index, route } from '@react-router/dev/routes';
 
export default [
  index('./home.tsx'),
  route('products/:pid', './product.tsx'),
];
Framework モード: 型付き loader
import { Route } from './+types/product.tsx';
 
export async function loader({ params }: Route.LoaderArgs) {
  const product = await getProduct(params.pid);
  return { product };
}
 
export default function Product({ loaderData }: Route.ComponentProps) {
  return <div>{loaderData.product.name}</div>;
}

Route.LoaderArgsRoute.ComponentProps で、paramsloaderData自動で型が付くのがポイントです。新規プロジェクトは create-react-router で雛形を作れます。Vite ベースなので、ビルド周りも素直です。

Remix はどこへ行ったのか

「Remix を使っていたけど、これからどうなるの?」という人も多いはずです。答えはシンプルで、React Router v7 は Remix v2 の「次のバージョン」です。Remix は React Router v7 に統合され、そのFramework モードが実質的に Remix の進化形になりました。

Remix v1 → Remix v2 → React Router v7(Framework モード)

つまり「Remix の loader / action / ネストルート」という資産は、React Router v7 の Framework モードにそのまま引き継がれています。Remix の歴史と v3で書いた流れの、現在の到達点がここです。

Next.js 以外の選択肢としての立ち位置

NOTE

React Router v7 の良さは、「必要なだけの段階を選べる」ことです。既存の React SPA は Declarative のまま動かし、データ層が欲しくなったら Data モードへ、SSR が要るなら Framework モードへ——と段階的に寄せられる。「最初からフルスタック前提」の Next.js App Router とは、ここの思想が違います。

ざっくりした使い分けの目安です。

状況向いている選択
既存の React SPA を活かしたいReact Router(Declarative → 段階的に拡張)
データ駆動だが SSR は不要React Router(Data モード)
SSR・フルスタックを React Router 流でReact Router(Framework モード/旧 Remix)
最初からフルスタック・RSC 前提Next.js App Router

「Next.js ほど重くしたくない」「既存 SPA を壊さず段階的にサーバー寄りへ寄せたい」案件で、React Router v7 は現実的な選択肢になります。

まとめ

  • React Router v7 は Declarative / Data / Framework の3モード。下にいくほど機能が増え、必要なだけ選べる
  • Declarative=従来のルーター、Dataloader/action のデータ駆動、Framework=Vite プラグインで SSR・型安全・コード分割まで
  • React Router v7 は Remix v2 の次版。Remix は統合され、Framework モードがその進化形
  • Framework モードはファイルベースルート+型付き Route Module(Route.LoaderArgs 等)。雛形は create-react-router
  • 「段階的に拡張できる」のが Next.js との思想差。既存 SPA を活かしつつサーバー寄りへ寄せたい現場に向く

「ただのルーター」という認識を一度アップデートすると、React Router v7 は「必要なところまで育てられるフレームワーク」として見えてきます。既存の React 資産があるほど、その段階性がありがたいはずです。

参考リンク