0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[React] React Router の基礎

Last updated at Posted at 2025-08-15

概要

  • Reactアプリケーションでページ遷移やルーティングを管理する React Router 6 の基本
  • createBrowserRouterRouterProvider を用いた、現代的で型安全なルーティング構造
  • 親子ルート構造(ネストルーティング)エラーバウンダリ の基本的な使い方

React Router 6 によって 「URL に応じたコンポーネント描画、ページ遷移管理、エラーハンドリング」 がシンプルかつ型安全に実現できる

実施条件

  • React + TypeScript プロジェクトが構築済みであること
  • TypeScript での型定義の基本が理解できていること
  • React コンポーネントの基本構造(関数コンポーネント、JSX)が理解できていること

環境

ツール バージョン 目的
Node.js 22.5.1 Reactアプリ実行環境
React 19.1.0 UI構築
TypeScript 4.9 型安全な開発
React Router 6.14 ルーティング管理

React Router 6 の基本構造

1. ディレクトリ構造例(基礎)

src/
├── routes/
│   ├── AppRouter.tsx       # ルーター統合: React Router 6 のルート定義、ネストルート、エラーバウンダリを管理
│   ├── routeConfig.ts      # ルート定義・型: URLパスの一元管理、型安全なルーティングを提供
│   └── index.ts            # エクスポート管理: バルクエクスポート
├── pages/
│   ├── HomeScreen/
│   │   └── HomeScreen.tsx
│   ├── IntroScreen/
│   │   └── IntroScreen.tsx
│   ├── FeatureA/
│   │   └── FeatureA.tsx
│   ├── FeatureB/
│   │   └── FeatureB.tsx
│   ├── xxx/
│   │   └── xxx.tsx
│   └── NotFound/
│       └── NotFound.tsx
├── App.tsx                 # トップレベルコンポーネント: AppRouterを呼び出してアプリ全体の構造を提供
└── index.tsx               # エントリーポイント: ReactDOM.createRootでApp.tsxをブラウザにマウント
  • ネストルーティングに対応しやすい構造
  • ルート設定・コンポーネント・エクスポートを分離
  • 将来的に FeatureWrapper や Layout を追加しやすい

2. エントリーポイント(index.tsx

// 1. importセクション
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';

// 2. 関数定義セクション
const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);

// 3.4 返り値構築・ロジックセクション
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

export {};
  • ReactDOM.createRoot でルートコンテナを生成
  • <App /> に全ルーター構造を統合
  • StrictMode により副作用のチェックや将来の互換性を向上

3. ルーター統合コンポーネント(App.tsx

// 1. importセクション
import React from 'react';
import { AppRouter } from './routes';
import './App.css';

// 2. 関数定義セクション
function App(): React.JSX.Element {
  // 3.4 返り値構築・ロジックセクション
  return (
    <div className="App">
      <AppRouter />
    </div>
  );
}

// 4. exportセクション
export default App;
export {};
  • ルーターを <AppRouter /> に集約
  • 親レイアウトやネストルートの管理はここで行わず、専用コンポーネントに任せる

4. ルート設定と型(routeConfig.ts

// ===== 1. ルート定義セクション =====
/** ルート名(キー)の型とルートパス(値)の型 の両方を、リテラル型として固定したオブジェクト型 */
export const routeConfig = {
  INTRO: '/',
  HOME: '/home',
  FEATURE_A: '/feature-a',
  FEATURE_B: '/feature-b',
  FEATURE_C: '/feature-c',
  HISTORY: '/history',
  SETTINGS: '/settings'
} as const;

// ===== 2. 型定義セクション =====
/** ルート名(キー)の型とルートパス(値)の型 */
export type RouteConfig = typeof routeConfig;

/** ルートパス(値)の型 */
export type RoutePath = RouteConfig[keyof RouteConfig];

// ===== 1. ルート定義セクション =====
/** フィーチャーID(キー)とルートパス(値)の両方を、リテラル型として固定したオブジェクト型 */
export const featureRouteMap = {
  featureA: routeConfig.FEATURE_A,
  featureB: routeConfig.FEATURE_B,
  featureC: routeConfig.FEATURE_C,
  history: routeConfig.HISTORY,
  settings: routeConfig.SETTINGS,
} as const;

// ===== 2. 型定義セクション =====
/** フィーチャーID(キー)の型 */
export type FeatureId = keyof typeof featureRouteMap;

// ===== 3. 関数定義セクション =====
/** フィーチャーIDからルートパスを取得 */
export const getRouteByFeatureId = (featureId: string): RoutePath | null =>
  featureRouteMap[featureId as FeatureId] || null;

/** ルートが実装済みかチェック */
export const isRouteImplemented = (route: RoutePath): boolean => {
  const implementedRoutes: RoutePath[] = [
    routeConfig.INTRO,
    routeConfig.HOME,
    routeConfig.FEATURE_A,
    routeConfig.FEATURE_B,
    routeConfig.FEATURE_C,
    routeConfig.HISTORY,
    routeConfig.SETTINGS
  ];
  return implementedRoutes.includes(route);
};
  • ルートパスを 一元管理 し、型安全に利用
  • FeatureId とルートをマッピングし、未実装機能の判定にも利用可能

5. ルーター構成(AppRouter.tsx

// ===== 1. importセクション =====
import React from 'react';
import { createBrowserRouter, RouterProvider, Outlet, useRouteError, isRouteErrorResponse } from 'react-router-dom';
import { routeConfig } from './routeConfig';
import { HomeScreen } from '../pages/HomeScreen';
import { IntroScreen } from '../pages/IntroScreen';
import { FeatureA } from '../pages/FeatureA';
import { FeatureB } from '../pages/FeatureB';
import { FeatureC } from '../pages/FeatureC';
import { History } from '../pages/History';
import { Settings } from '../pages/Settings';
import { NotFound } from '../pages/NotFound';

// 未実装画面用のプレースホルダー
const ComingSoon: React.FC = () => <div>Coming Soon</div>;

// ===== 2. 関数定義セクション =====

// 2.1 エラーバウンダリコンポーネント
const RootErrorBoundary: React.FC = () => {
  const error = useRouteError();
  if (isRouteErrorResponse(error)) {
    return (
      <div>
        <h1>{error.status} - {error.statusText}</h1>
        {error.data?.message && <p>{error.data.message}</p>}
      </div>
    );
  }
  return <div>Something went wrong</div>;
};

// 2.2 レイアウトコンポーネント
const AppLayout: React.FC = () => (
  <div className="app-layout">
    <Outlet />
  </div>
);

// 2.3 ルーター作成コンポーネント
export const AppRouter = () => {
  const router = createBrowserRouter([
    {
      path: "/",
      element: <AppLayout />,
      errorElement: <RootErrorBoundary />,
      children: [
        { path: routeConfig.INTRO, element: <IntroScreen />, index: true },
        { path: routeConfig.HOME, element: <HomeScreen /> },
        { path: routeConfig.FEATURE_A, element: <FeatureA /> },
        { path: routeConfig.FEATURE_B, element: <FeatureB /> },
        { path: routeConfig.FEATURE_C, element: <FeatureC /> },
        { path: routeConfig.HISTORY, element: <ComingSoon /> },
        { path: routeConfig.SETTINGS, element: <ComingSoon /> },
        { path: "*", element: <NotFound /> }
      ]
    }
  ]);

  // 3.4 返り値構築・ロジックセクション
  return <RouterProvider router={router} />;
};

// 4. exportセクション
export default AppRouter;
  • 親ルート / に AppLayout を配置
  • children 配列でページコンポーネントをネスト
  • errorElement でルートレベルのエラーを統合的にハンドリング

まとめ

  • React Router 6 では createBrowserRouterRouterProvider が中心
  • ルート定義を型安全に管理すると、開発効率と保守性が向上
  • 親子ルート・エラーバウンダリ・未実装機能判定などを組み合わせることで 現代的で堅牢なルーティング が構築可能

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?