React Router V6 で useRoutes() が Router コンテキスト外で使用されるエラーの解決方法
問題の説明
React Router V6 で useRoutes()
フックを使用する際に、以下のエラーが発生することがあります:
Error: useRoutes() may be used only in the context of a <Router> component.
このエラーは、React Router の機能(useRoutes
、Routes
、Route
など)が適切な Router コンテキスト外で使用されている場合に発生します。
原因
React Router V6 では、すべてのルーティング機能が Router コンテキストを必要とします。このコンテキストは BrowserRouter
、HashRouter
、MemoryRouter
などの Router コンポーネントによって提供されます。
主な原因は以下の通りです:
- Router コンポーネントでアプリケーションがラップされていない
- 異なるバージョンの react-router-dom が混在している
- 誤ったインポート(react-router と react-router-dom の混同)
解決方法
方法 1: アプリケーションを BrowserRouter でラップする
最も一般的な解決策は、アプリケーション全体を BrowserRouter
コンポーネントでラップすることです。
index.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>
);
TIP
アプリケーションのエントリーポイント(index.js)で Router を設定するのがベストプラクティスです。これにより、アプリ全体でルーティング機能が利用可能になります。
方法 2: App.js 内で Router を設定する
エントリーポイントを変更できない場合は、App.js 内で対応することも可能です。
App.js
import { BrowserRouter, useRoutes } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
// 他のページインポート
const AppRoutes = () => {
const routes = useRoutes([
{ path: '/', element: <Home /> },
{ path: 'o-nama', element: <About /> },
// 他のルート定義
]);
return routes;
};
const App = () => {
return (
<BrowserRouter>
<AppRoutes />
</BrowserRouter>
);
};
export default App;
方法 3: インポートの確認
誤ったモジュールからのインポートがないか確認してください。
間違ったインポート(動作しない)
import { Routes, Route } from 'react-router'; // 誤り
正しいインポート
import { Routes, Route } from 'react-router-dom'; // 正しい
WARNING
react-router
と react-router-dom
は別パッケージです。Web アプリケーションでは必ず react-router-dom
からインポートしてください。
方法 4: パッケージのバージョン確認
複数のバージョンの react-router-dom がインストールされていないか確認してください。
npm list react-router-dom
# または
yarn list react-router-dom
複数のバージョンが検出された場合は、全てのパッケージをアンインストール後、最新バージョンを再インストールします。
npm uninstall react-router-dom
npm install react-router-dom@latest
完全な実装例
以下に、React Router V6 を正しく使用する完全な実装例を示します。
index.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>
);
App.js
import { useRoutes } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Services from './pages/Services';
import Gallery from './pages/Gallery';
import Prices from './pages/Prices';
import Contact from './pages/Contact';
const App = () => {
const routes = useRoutes([
{ path: '/', element: <Home /> },
{ path: 'o-nama', element: <About /> },
{ path: 'usluge', element: <Services /> },
{ path: 'galerija', element: <Gallery /> },
{ path: 'cjenovnik', element: <Prices /> },
{ path: 'kontakt', element: <Contact /> }
]);
return routes;
};
export default App;
INFO
React 18 では ReactDOM.render
の代わりに ReactDOM.createRoot
を使用します。古いバージョンの React を使用している場合は適宜読み替えてください。
まとめ
useRoutes() may be used only in the context of a <Router> component
エラーは、React Router の機能が適切なコンテキスト外で使用されている場合に発生します。この問題を解決するには:
- アプリケーションを
BrowserRouter
でラップする - 正しいパッケージからインポートしているか確認する(
react-router-dom
) - パッケージのバージョン競合がないか確認する
これらの対策により、React Router V6 の機能を正しく利用できるようになります。