react-router vs react-router-dom vs @reach/router vs react-router-native
React エコシステムにおけるルーティングライブラリの選定とアーキテクチャ
react-routerreact-router-dom@reach/routerreact-router-native類似パッケージ:

React エコシステムにおけるルーティングライブラリの選定とアーキテクチャ

@reach/routerreact-routerreact-router-domreact-router-native は、すべて React アプリケーションにおける画面遷移と URL 管理を担うライブラリですが、役割と維持状況が異なります。react-router はプラットフォームに依存しないコアロジックを提供し、react-router-dom は Web ブラウザ環境向けの実装、react-router-native は React Native 向けの実装です。一方、@reach/router はかつてアクセシビリティを重視した軽量ルーターでしたが、現在は react-router v6 に統合され、公式に非推奨(deprecated)となっています。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
react-router27,773,97056,3214.18 MB15625日前MIT
react-router-dom24,114,70156,3215.46 kB15625日前MIT
@reach/router441,0226,849-1736年前MIT
react-router-native41,09456,32140.2 kB1562ヶ月前MIT

React ルーティングライブラリ完全比較:コア、DOM、Native、そして legacy

React エコシステムにおいて、画面遷移と URL 管理はアプリケーションの構造を決定づける重要な要素です。react-router シリーズは業界標準として広く採用されていますが、パッケージが複数存在するため、初学者やアーキテクチャ選定時に混乱を招くことがあります。特に、かつて人気を博した @reach/router の扱いと、react-router コアと各プラットフォーム実装(DOM、Native)の関係性を正しく理解することが、堅牢なアプリケーション構築の第一歩です。

📦 パッケージの役割と関係性

これら 4 つのパッケージは、同じ「ルーティング」という目的を持ちつつも、レイヤーと対象環境が明確に異なります。

react-router は「コア」です。

  • プラットフォーム(Web か Native か)に依存しない共通のロジックを含みます。
  • 単独で完結することは少なく、通常は下位互換レイヤーとして機能します。

react-router-dom は「Web 向け実装」です。

  • ブラウザの History API や DOM 操作に必要なコンポーネントを提供します。
  • Web アプリ開発では、これと react-router を同時にインストールするのが一般的です。

react-router-native は「モバイル向け実装」です。

  • React Native 環境でのナビゲーションに特化しています。
  • Web 固有の機能(<a> タグなど)をネイティブコンポーネントに置き換えます。

@reach/router は「過去の遺産」です。

  • かつては軽量でアクセシビリティに優れていましたが、開発が終了しました。
  • 機能は react-router v6 へ吸収され、現在は非推奨です。

🏗️ 実装の違い:Web vs Native vs Core

パッケージごとに提供されるコンポーネントやフックには、環境に応じた違いがあります。特にルーターの初期化とリンクの扱いに注目します。

react-router-dom では、ブラウザの URL バーと同期する BrowserRouter を使用します。

// react-router-dom: Web 環境
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      <nav><Link to="/about">About</Link></nav>
      <Routes>
        <Route path="/" element={<Home />} />
      </Routes>
    </BrowserRouter>
  );
}

react-router-native では、ネイティブのスタックナビゲーションを模倣した NativeRouter を使用します。

// react-router-native: React Native 環境
import { NativeRouter, Routes, Route, Link } from 'react-router-native';

function App() {
  return (
    <NativeRouter>
      <Link to="/about"><Text>About</Text></Link>
      <Routes>
        <Route path="/" element={<Home />} />
      </Routes>
    </NativeRouter>
  );
}

react-router (コア) は、環境固有のラッパーなしでフックや低レベルコンポーネントを提供します。

// react-router: コアロジック(共通部分)
import { useNavigate, useParams } from 'react-router';

function UserProfile() {
  const navigate = useNavigate();
  const { id } = useParams();
  // プラットフォームに依存しないナビゲーションロジック
  return <button onClick={() => navigate(`/user/${id}`)}>View</button>;
}

@reach/router は、v6 以前の独自 API を使用していました(現在は使用非推奨)。

// @reach/router: 非推奨(レガシーコード例)
import { Router, Link } from '@reach/router';

// 現在の react-router-dom とは API が異なる
function App() {
  return (
    <Router>
      <Link to="/about">About</Link>
      {/* v6 以降の Routes/Route 構造とは異なる */}
    </Router>
  );
}

🔄 データ取得とローディング状態

現代のルーティングでは、画面遷移に伴うデータ取得の扱いが重要です。react-router v6.4 以降では、データ API が強化されました。

react-router-dom では、loader を使ってルート遷移前にデータを取得できます。

// react-router-dom: Data API
import { createBrowserRouter, useLoaderData } from 'react-router-dom';

const router = createBrowserRouter([
  {
    path: "/user/:id",
    element: <UserProfile />, 
    loader: async ({ params }) => {
      return fetch(`/api/user/${params.id}`);
    }
  }
]);

function UserProfile() {
  const data = useLoaderData(); // loader の結果を直接取得
  return <div>{data.name}</div>;
}

react-router-native でも同様のデータパターンが利用可能ですが、ネットワーク層の扱いに注意が必要です。

// react-router-native: Data API
import { createStaticRouter, RouterProvider } from 'react-router-native';

// ネイティブ環境でも loader パターンは有効
const router = createStaticRouter([
  {
    path: "/user/:id",
    loader: async ({ params }) => {
      // ネイティブの fetch または API 呼び出し
      return fetchMobileAPI(params.id);
    }
  }
]);

react-router コア自体はデータ取得ロジックを持ちませんが、これらの実装を支える基盤となります。

// react-router: コア
// データ取得自体は実装パッケージ(dom/native)に依存するが、
// 状態管理のコンテキストはここで定義されている

@reach/router には、標準のデータ取得パターン(loader など)は存在しませんでした。

// @reach/router: 標準のデータ取得機能なし
// useEffect 内で fetch を行う必要があり、コードが散乱しがちだった
function User({ id }) {
  const [user, setUser] = useState(null);
  useEffect(() => { fetchUser(id).then(setUser) }, [id]);
  // ...
}

⚠️ 保守性と将来性

パッケージの選定において、メンテナンス状況は技術的負債に直結します。

  • @reach/router: 開発終了。セキュリティアップデートも期待できません。移行が必要です。
  • react-router シリーズ: 活発にメンテナンスされています。v6 から v7 へ進化中で、TypeScript のサポートも強化されています。

🤝 共通点:React エコシステムとの統合

これら(@reach/router を除く現行バージョン)は、React の思想に深く根ざしています。

1. ⚛️ フックベースの API

  • useNavigateuseLocationuseParams などのフックが共通して利用可能です。
// どのパッケージでも共通のフック利用
import { useLocation } from 'react-router'; // or react-router-dom

function CurrentPath() {
  const location = useLocation();
  return <span>Current: {location.pathname}</span>;
}

2. 🧩 宣言的ルーティング

  • JSX でルート構造を定義するスタイルは一貫しています。
// 宣言的ルート定義
<Routes>
  <Route path="/home" element={<Home />} />
</Routes>

3. 🔒 型安全性 (TypeScript)

  • 現行の react-router シリーズは型定義が整備されています。
// TypeScript での型推論
import { Link } from 'react-router-dom';

// to プロパティの型チェックが効く
<Link to="/about" /> 

📊 選定マトリクス

特徴react-router-domreact-router-nativereact-router (Core)@reach/router
対象環境Web ブラウザReact Native共通ロジックWeb (Legacy)
主要コンポーネントBrowserRouter, LinkNativeRouter, LinkRouter, RoutesRouter, Link
データ取得loader 対応loader 対応非依存非対応
保守状況✅ アクティブ✅ アクティブ✅ アクティブ❌ 非推奨
推奨度⭐⭐⭐⭐⭐ (Web)⭐⭐⭐⭐⭐ (Native)⭐⭐⭐⭐ (ライブラリ開発)⭐ (移行推奨)

💡 結論:何をすべきか

Web アプリケーションを構築する場合 迷わず react-router-dom を選択してください。これが事実上の標準です。react-router も同時にインストールされますが、直接インポートするのはフックなど共通機能に限られます。

React Native アプリを構築する場合 react-router-native を使用します。ただし、React Native 界隈では react-navigation も強力な競合であり、ネイティブ固有のジェスチャーやスタック管理を重視する場合は比較検討が必要です。

@reach/router を使っている場合 技術的負債を抱えている状態です。react-router-dom v6 への移行計画をすぐに立てるべきです。API の類似性が高いので、移行コストは比較的低く抑えられます。

ライブラリ開発者である場合 プラットフォームに依存しないルーティングロジックを実装したい場合のみ、react-router コアを直接参照します。ただし、多くの場合は各プラットフォーム向けにラッパーを提供することになります。

最終的に、現代の React 開発において「ルーティング=react-router シリーズ」という図式は変わっていません。重要なのは、その中で「どの環境向けのパッケージを選ぶか」を明確にすること、そして「過去の資産(@reach/router)に縛られないこと」です。

選び方: react-router vs react-router-dom vs @reach/router vs react-router-native

  • react-router:

    プラットフォーム固有の実装(DOM や Native)に依存しない共通のルーティングロジックやフック(useNavigate など)を共有したい場合に選択します。通常、単独ではなく react-router-domreact-router-native の依存パッケージとして間接的に利用されます。

  • react-router-dom:

    Web ブラウザ上で動作する React アプリケーション(SPA、SSR など)を構築する際の標準的な選択です。BrowserRouterLink コンポーネントなど、Web 固有の機能が必要な場合は必ずこのパッケージを使用します。

  • @reach/router:

    新規プロジェクトでの使用は避けるべきです。このパッケージは開発が終了し、機能の多くが react-router v6 へ統合されました。既存のレガシーコードを維持する場合を除き、代わりに react-router-dom の採用を検討してください。

  • react-router-native:

    React Native を使用して iOS や Android のネイティブモバイルアプリを開発する場合に選択します。Web 固有の機能(history API など)の代わりに、ネイティブ環境に適したナビゲーションコンポーネントを提供します。

react-router のREADME

react-router is the primary package in the React Router project.

Installation

npm i react-router