React Routerのmeta・title設定と基本ルーティング|v8対応入門
React Routerは、Reactのシングルページアプリケーション(SPA)でURLと画面を紐付けるための標準的なルーティングライブラリです。最新は2026年6月17日リリースのv8で、v7からの移行負荷は小さいメジャーアップグレードです。本記事はBrowserRouterによる基本のルート設定から、検索でも需要の高いページのtitle・meta設定(React 19のネイティブ機能とフレームワークモードのmetaexport)、頻出する「No routes matched location」エラーの対処までを、動くコードとともに整理します。React Routerには書き方の異なる3つのモードがあるため、まず自分がどのモードかを確認してから読み進めてください。
まとめ:React Routerの要点
- 基本構成:
BrowserRouterでアプリを包み、Routes/Routeでパスとコンポーネントを対応させる。 - 3モード:宣言的モード(BrowserRouter)/データモード(createBrowserRouter)/フレームワークモード(route moduleで
loader・meta等をexport)。使える機能がモードで変わる。 - title・meta設定:React 19なら
<title>・<meta>をコンポーネントに直接書けば<head>へ巻き上がる。フレームワークモードではmetaexport、重複制御が要る場合はreact-helmet-async。 - 最新版:v8(2026-06)。パッケージは
react-routerに統合済み(react-router-domはv8で廃止)。 - 頻出エラー:「No routes matched location」はパス不一致か
Router未設置が主因。
以下、各項目をコード付きで解説します。データ取得(loader・action)はモード依存で扱いが大きいため、詳細は専用記事に譲ります。
React Routerとは:SPAでのルーティングの役割
SPAはページ全体を再読み込みせずJavaScriptで画面を切り替えます。このときブラウザのURLと表示コンポーネントを同期させるのがReact Routerの役割です。URLの変化を検知して対応するコンポーネントを描画し、ブラウザの戻る・進むボタンやブックマーク、URL直接入力にも対応させます。React本体にルーティング機能はないため、Web向けSPAでは事実上の標準として使われます。
React Routerには目的別に3つの利用モードがあり、書き方と使える機能が異なります。BrowserRouterでJSX的にルートを書く宣言的モード、createBrowserRouterでルート定義オブジェクトを作りデータ取得を組み込むデータモード、そしてファイル単位のルートモジュールにloader・action・metaなどをexportしてサーバーレンダリング(SSR)まで含めるフレームワークモードです。本記事は導入しやすい宣言的モードを軸に、title・meta設定でフレームワークモードにも触れます。フレームワークモードのデータ取得はReact Router v7でのデータローディングとアクションの活用方法で詳しく扱っています。
React Routerの導入とプロジェクト設定
パッケージのインストール(react-router / react-router-dom)
v7以降、パッケージはreact-routerに一本化されました。新規はこれを入れます。
npm install react-router
v7では従来のreact-router-domもreact-routerを再エクスポートするパッケージとして動きますが、v8で廃止されました。既存プロジェクトをv8へ上げる場合は、import元をreact-router-domからreact-routerへ、RouterProviderなど一部のDOM束縛はreact-router/domへ差し替えます。以下のコード例はv7でも動くreact-router-dom表記で示しますが、正確な最新のimportパスは公式ドキュメントで確認してください。
create-react-routerテンプレートによる雛形生成
SSRや型安全なloaderを最初から使うフレームワークモードは、公式テンプレートで雛形を作れます。
npx create-react-router@latest my-app
生成されるapp/routes.tsにルート定義、各ルートモジュールにloaderやmetaをexportする構成になります。Viteベースの開発サーバーとHMR、ビルド最適化が同梱されます。単純なクライアント専用SPAならテンプレートは不要で、下記のBrowserRouterから始めれば十分です。
基本のルーティング記述(BrowserRouter / Routes / Route)
宣言的モードの最小構成は、アプリ全体をBrowserRouterで包み、Routesの中にRouteを並べてパスとコンポーネントを対応させます。エントリーポイント(main.tsxなど)で一度だけBrowserRouterを設置するのが原則です。以下の例はv7互換のreact-router-dom表記です(v8ではreact-routerからimportします)。
import { BrowserRouter, Routes, Route } from "react-router-dom";
import ReactDOM from "react-dom/client";
import Home from "./pages/Home";
import About from "./pages/About";
import NotFound from "./pages/NotFound";
ReactDOM.createRoot(document.getElementById("root")).render(
<BrowserRouter>
<Routes>
<Route index element={<Home />} />
<Route path="about" element={<About />} />
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
);
index属性を付けたRouteは親パスそのもの(ここではトップ)に対応します。path="*"はどのルートにも一致しなかったとき描画される受け皿で、404ページに使います。この*ルートを置かないと、未定義パスで「No routes matched location」エラーが発生します。
画面遷移には<a>ではなく<Link>を使います。<a>はページ全体を再読み込みしてSPAの利点を失うためです。現在地の判定が要るメニューには<NavLink>を使い、一致時にisActiveを受け取ってスタイルを切り替えます。フォーム送信後など、コードから遷移させたい場合はuseNavigateフックを使います。
import { Link, NavLink, useNavigate } from "react-router-dom";
function Nav() {
const navigate = useNavigate();
return (
<nav>
<Link to="/about">会社情報</Link>
<NavLink to="/contact" className={({ isActive }) => isActive ? "active" : ""}>
お問い合わせ
</NavLink>
<button onClick={() => navigate("/")}>トップへ</button>
</nav>
);
}
navigate(-1)のように数値を渡すと履歴の戻る・進むを操作できます。UIライブラリのボタンやタブと組み合わせる画面遷移はMaterial-UIとReact Routerを統合した画面遷移の実現方法で具体例を確認できます。
動的ルーティングとパラメータ取得(useParams)
商品詳細やユーザーページのようにIDで内容を切り替えるルートは、パスに:idのような可変部分(URLパラメータ)を書き、useParamsで取り出します。
import { Route } from "react-router-dom";
import { useParams } from "react-router-dom";
// ルート定義(Routes内に配置する)
<Route path="products/:id" element={<ProductDetail />} />
// パラメータを受け取るコンポーネント
function ProductDetail() {
const { id } = useParams();
return <p>商品ID: {id}</p>;
}
useParamsが返す値は常に文字列です。数値として使うならNumber(id)で変換し、存在しないIDのときは前述の受け皿ルートやデータ取得側で404扱いにします。パスに含めない検索条件やフィルタは?key=valueのクエリ文字列で扱い、型安全なURLクエリパラメータ管理ライブラリnuqs 2.5.0のようなライブラリを使えばクエリを型付きで読み書きしURLと状態を同期できます。
ネストルートと共通レイアウト(Outlet)
ヘッダーやサイドバーを複数ページで共有するには、親ルートに共通レイアウトを置き、子ルートをその中に描画します。親コンポーネントで<Outlet>を書いた位置に、一致した子ルートの内容が差し込まれます。
import { Outlet } from "react-router-dom";
function Layout() {
return (
<div>
<Header />
<main><Outlet /></main>
</div>
);
}
<Route element={<Layout />}>
<Route path="dashboard" element={<Dashboard />} />
<Route path="settings" element={<Settings />} />
</Route>
ネストによりレイアウトの再利用性が上がり、共通部分の再描画も避けられます。子ルートごとにデータを取得する場合は、宣言的モードでは各コンポーネント内で取得し、データモード・フレームワークモードではloaderでルート単位に取得を分離できます。
ページタイトルとmeta情報の設定(title・meta・OGP)
SPAは初期HTMLの<head>が全ページ共通になりがちで、ルートごとにtitleやmeta descriptionを出し分けないとSEOとSNSシェアで不利になります。設定方法は使っているReactとReact Routerのモードで変わります。まず結論として、React 19以降は追加ライブラリなしで書けるようになったのが最大の変化です。
React 19のネイティブメタデータ(helmet不要)
React 19では、コンポーネントのどこに<title>・<meta>・<link>を書いても、Reactが自動で<head>へ巻き上げます。エフェクトもプロバイダも不要です。
function ProductDetail() {
const { id } = useParams();
return (
<>
<title>{`商品 ${id} | ストア名`}</title>
<meta name="description" content="商品の詳細ページです" />
<meta property="og:title" content="商品詳細" />
<h1>商品 {id}</h1>
</>
);
}
クライアントレンダリングでもSSRでも動きます。ただしReactは巻き上げるだけで重複排除はしないため、親子で同名タグを二重に書くと<title>が複数出ることがあります。ルート単位で確実に上書きしたい場合は次のhelmet-asyncが依然有効です。
react-helmet-asyncを使う場面
React 18以前を使っている、または重複排除やルート横断の上書きを厳密に制御したい場合はreact-helmet-asyncを使います。アプリをHelmetProviderで包み、各ページで<Helmet>にタグを書くと、後にマウントされたものが優先されます。
import { Helmet } from "react-helmet-async";
<Helmet>
<title>お問い合わせ | ストア名</title>
<meta name="description" content="お問い合わせフォーム" />
</Helmet>
フレームワークモードのmeta export
フレームワークモード(create-react-router構成)では、ルートモジュールからmeta関数をexportし、rootの<head>に置いた<Meta>コンポーネントが描画します。「react router meta」で検索した際に想定される、React Router公式のメタ設定方法がこれです。
export function meta() {
return [
{ title: "商品一覧 | ストア名" },
{ name: "description", content: "取り扱い商品の一覧です" },
{ property: "og:title", content: "商品一覧" },
];
}
最後にマッチしたルートのmetaが採用され、返した配列で<head>のメタを丸ごと置換します(親のmetaとマージはされません)。v8では引数のプロパティがdataからloaderDataへ変更され、loaderが返した値をmetaに反映できます。なお公式は、React 19以降はこのmetaexportよりルートコンポーネント内に<title>・<meta>を直接書く方法を推奨しています。
title・meta設定方法の選択基準
判断はシンプルです。React 19以降なら、まず組み込みの<title>・<meta>直書きから始めます。追加依存が増えず、宣言的モードでもフレームワークモードでも動きます。重複したtitleが出て制御しきれない、あるいはReact 18以前に留まっている場合だけhelmet-asyncを足します。フレームワークモードでSSR配信し、loaderで取得したデータをtitleに反映したいならmetaexportが噛み合います。逆に、単純なクライアント専用SPAでフレームワークモードのためだけに構成を作り直すのは過剰で、避けるべきです。
React Router v8・v7とモードの違い
最新のv8は2026年6月17日リリースで、v7.18.0(2026年6月16日)が最終のv7でした。v7からv8への移行負荷は小さく(主な作業はパッケージ統合への追従)、v7もセキュリティ更新が続きます。大きな変更はパッケージ整理(react-router-dom廃止→react-router)と、metaのAPIがdataからloaderDataへ移った点です。破壊的な変更はimport元の差し替えが中心です。
混同しやすいのはバージョンよりモードの違いです。宣言的モードはBrowserRouterでJSX的にルートを書く最も手軽な形で、本記事の基本コードはこれです。データモードはcreateBrowserRouter+RouterProviderでルート定義にloader・actionを組み込みます。フレームワークモードはさらにSSR・型生成・ファイルベースのルートモジュールまで含みます。loader・actionによるデータ取得と更新の具体はReact Router v7でのデータローディングとアクションの活用方法にまとめています。ルーティングの選択肢を広く比較したい場合はTanStack Routerとは何か(React Routerとの比較)も参考になります。
よくあるエラーと対処法
実際の検索でも多い代表的なつまずきを、原因と確認順に整理します。
- No routes matched location:指定パスに一致する
Routeが無い状態。パスのスペルミス、先頭スラッシュの有無、path="*"の受け皿未設置を確認する。ネスト時は親のpathと子の相対パスの結合結果を見る。 - useNavigate() may be used only in the context of a Router:
useNavigateなど各種フックをBrowserRouterの外側で呼んでいる。フックを使うコンポーネントがRouterの内側に入っているか確認する。 - useParamsで値が取れない:Route側の
:idとコンポーネントで参照するキー名が不一致。path="products/:id"ならuseParams()のキーもidにそろえる。 - リダイレクトが効かない:宣言的モードでは
<Navigate to="/login" replace />を描画する。条件分岐の外にreturnが漏れていないか、replaceの付け忘れで履歴が積み上がっていないかを見る。 - 404ページが出ない・意図しない画面になる:
path="*"ルートの位置と、より具体的なルートとの優先順位を確認する。v6以降はルートの記述順ではなく一致度で選ばれる。
なお、React Server Components(RSC)由来の脆弱性であるReact2Shell(CVE-2025-55182)の対応手順では、React Routerを含む消費側フレームワークも影響を受けました。React Router自体の欠陥ではありませんが、本番運用ではReactとReact Routerをともに最新のパッチに保つことも合わせて確認してください。
よくある質問
React Routerとは何ですか?
ReactのSPAでURLと表示コンポーネントを紐付ける標準的なルーティングライブラリです。React本体にはルーティング機能がないため、ページ全体を再読み込みせずに画面を切り替えるWebアプリで広く使われます。
React Routerでページのtitleやmetaを設定するには?
React 19以降はコンポーネント内に<title>・<meta>を直接書けば<head>へ巻き上がります。フレームワークモードではルートモジュールのmetaexportを使い、重複制御が要る場合はreact-helmet-asyncを併用します。
「No routes matched location」はなぜ出ますか?
指定したURLに一致するRouteが定義されていないためです。パスの綴りや先頭スラッシュを確認し、未定義パスの受け皿としてpath="*"のRouteを用意すると解消します。
react-helmet-asyncはまだ必要ですか?
React 19の単純な用途では不要です。ネイティブのメタデータ機能で足ります。ただしReactが重複排除をしないため、複数titleの上書き制御やReact 18以前の環境では引き続き有効です。
React Router v8へアップグレードすべきですか?
v7からv8は移行負荷が小さいメジャーアップグレードのため、基本は上げて問題ありません。破壊的変更は主にimport元をreact-router(DOM束縛はreact-router/dom)へ統一することです。急がない場合もv7はセキュリティ更新が続くため、パッチ適用は継続してください。