Skip to content

React Router v6 "A <Route> is only ever to be used as the child of <Routes>" エラーの解決方法

問題点

Reactアプリケーションでルーティングを実装する際、以下のようなエラーが発生することがあります:

Error: A <Route> is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your Route in a Routes.

このエラーは、React Routerのバージョン6で導入された新しい構文規則に従っていない場合に発生します。

エラーの原因

React Router v6では、ルーティングの定義方法がv5から大幅に変更されました:

  1. RouteコンポーネントはRoutesコンポーネントの子要素である必要がある
  2. コンポーネントの指定方法がelementプロパティを使用する形に変更された
  3. SwitchコンポーネントがRoutesコンポーネントに置き換えられた

古いチュートリアルやv5のコードをそのままv6で使用すると、このエラーが発生します。

解決方法

基本的な修正方法

js
import { Routes, Route } from "react-router-dom";
import Welcome from "./Pages/Welcome";
import Game from "./Pages/Game";
import Leaderboard from "./Pages/Leaderboard";

function App() {
  return (
    <div>
      <Routes>
        <Route path="/welcome" element={<Welcome />} />
        <Route path="/game" element={<Game />} />
        <Route path="/leaderboard" element={<Leaderboard />} />
      </Routes>
    </div>
  );
}

export default App;
js
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from "./App";

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById('root')
);

主な変更点

  • Routesコンポーネントのインポートを追加
  • RouteコンポーネントをRoutesでラップ
  • コンポーネントの指定方法を子要素からelementプロパティに変更

より実践的な例

js
import { Routes, Route } from "react-router-dom";
import Header from "./components/Header";
import Footer from "./components/Footer";
import Home from "./pages/Home";
import About from "./pages/About";
import Contact from "./pages/Contact";

function App() {
  return (
    <>
      <Header />
      <main>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
          <Route path="/contact" element={<Contact />} />
        </Routes>
      </main>
      <Footer />
    </>
  );
}

export default App;
js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>
);

useRoutesフックを使用する方法

React Router v6では、JSXではなくオブジェクト形式でルートを定義することもできます:

js
import { useRoutes } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import Contact from "./pages/Contact";

function App() {
  const routes = useRoutes([
    { path: "/", element: <Home /> },
    { path: "/about", element: <About /> },
    { path: "/contact", element: <Contact /> }
  ]);
  
  return routes;
}

export default App;

バージョンに関する注意点

WARNING

このエラーはReact Router v6特有の問題です。古いバージョン(v5)のコードをv6で実行すると発生します。

バージョンダウングレードの方法

一時的な解決策としてv5にダウングレードすることも可能ですが、新機能が使えないため非推奨です:

bash
npm install react-router-dom@5.3.0

よくある間違いと修正

以下はよくある間違った実装とその修正例です:

誤った実装例と修正方法

誤り: RouteがRoutesでラップされていない

js
// 間違い
<Route path="/home" element={<Home />} />
<Route path="/about" element={<About />} />

// 正しい
<Routes>
  <Route path="/home" element={<Home />} />
  <Route path="/about" element={<About />} />
</Routes>

誤り: コンポーネントを子要素として指定

js
// 間違い(v5の書き方)
<Route path="/home">
  <Home />
</Route>

// 正しい(v6の書き方)
<Route path="/home" element={<Home />} />

まとめ

React Router v6では、ルーティング定義の構文が以下のように変更されました:

  1. RoutesコンポーネントでRouteをラップする
  2. コンポーネントはelementプロパティで指定する
  3. SwitchRoutesに置き換えられた
  4. exactプロパティは削除された(デフォルトで完全一致)

新しい構文に適応することで、より宣言的でパフォーマンスの高いルーティングを実装できます。公式ドキュメントを参照して、最新のベストプラクティスに従うことをお勧めします。