React Router バージョン5から6への移行:API変更点と実装パターン比較

ルーティング定義とレンダリングの再設計

React Router 6 では、パスの一致判定エンジンが見直され、以前よりも直感的なマッチングロジックが採用されています。主な変更点は、従来の <Switch> コンポーネントの廃止と、新しい <Routes> 要素への移行です。これにより、複数のルートが同時に評価されるようになり、ネスト構造の管理が容易になりました。また、component プロパティの代わりに element を直接使用し、JSX をそのまま渡す形式へ統一されています。

// React Router 5 の従来の記法
import { Switch, Route } from 'react-router-dom';

const LegacyRouter = () => (
  <Switch>
    <Route exact path="/panel" component={DashboardView} />
    <Route path="/account/:uuid" component={AccountDetails} />
  </Switch>
);

// React Router 6 の新規記法
import { Routes, Route } from 'react-router-dom';

const ModernRouter = () => (
  <Routes>
    <Route path="/panel" element={<DashboardView />} />
    <Route path="/account/:identifier" element={<AccountDetails />} />
  </Routes>
);

ナビゲーション操作のフック中心化

プログラム的な画面遷移や履歴スタックの制御について、v5 では withRouter 高階関数やクラスインスタンスの this.props.history に依存していましたが、v6 ではすべての関数コンポーネント向けに useNavigate フックが提供されます。これにより、コンポーネントのライフサイクルに左右されず、クリーンなコードでページ移動やバック操作を実装可能になります。

// v5: HOC を介した history 参照
import { withRouter } from 'react-router-dom';

const OldNavigationBtn = ({ history }) => {
  const submitForm = () => history.push('/confirm/order-778');
  return <button onClick={submitForm}>次へ進む</button>;
};
export default withRouter(OldNavigationBtn);

// v6: カスタムフックを使用した遷移処理
import { useNavigate } from 'react-router-dom';

const NewNavigationBtn = () => {
  const navigateTo = useNavigate();
  const submitForm = () => navigateTo('/confirm/order-778');
  return <button onClick={submitForm}>次へ進む</button>;
};

パスパラメータの抽出方法

URL から動的な値を取得する際、v5 ではループ内やレンダープロップスを介して match.params オブジェクトを展開する必要がありましたが、v6 では useParams フック単独で取得できるよう設計が変更されました。

// v5: match オブジェクトからの展開
const V5Profile = ({ match }) => {
  const targetId = match.params.uuid;
  return <h2>ユーザーID: {targetId}</h2>;
};

// v6: フック直結での取得
const V6Profile = () => {
  const { identifier } = useParams();
  return <h2>ユーザーID: {identifier}</h2>;
};

リンク要素とアクティブ状態の判定

ナビゲーションバーなどで現在のページに該当するリンクにスタイルを当てる場合、v5 の NavLink コンポーネントで指定していた activeClassNameactiveStyle は撤廃されました。代わりに、Link または NavLinkclassName 属性に関数を割り当て、引数の isActive フラグを用いて条件付きで文字列またはスタイルオブジェクトを返す方式へ移行します。

// v5: 固定クラス名の付与
<NavLink to="/home" activeClassName="menu-highlight">
  メイン画面
</NavLink>

// v6: 関数型 ClassName の適用
<Link to="/home" className={({ isActive }) => isActive ? 'menu-highlight' : ''}>
  メイン画面
</Link>

リダイレクト処理の実装差分

認証チェックや旧URLからのフォールバックなどに利用されていた <Redirect> コンポーネントは、v6 で <Navigate> に名称変更されました。内部的な再レンダリングの仕組みが最適化されているため、パフォーマンス面でも改善が期待できます。論理演算子や条件付きレンダリングと組み合わせて、遷移先のパスを宣言的に設定できます。

// v5: Redirect コンポーネントの埋め込み
const AuthGuardV5 = ({ isLoggedIn, children }) => {
  if (!isLoggedIn) {
    return <Redirect to="/sign-in" push />;
  }
  return children;
};

// v6: Navigate コンポーネントによる分岐
const AuthGuardV6 = ({ isLoggedIn, children }) => {
  if (!isLoggedIn) {
    return <Navigate to="/sign-in" replace />;
  }
  return children;
};

タグ: react-router v5 v6 react-hooks navigation-patterns

7月8日 16:13 投稿