犯人はこいつです
前提(主なパッケージ)
"dependencies": {
"@emotion/styled": "^11.14.1",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"react-router": "^7.9.6"
"@mui/icons-material": "7.2.0",
}
はじめに
新たな画面を作成するにあたり、新たなルーティング (URL・ビューの対応付け) を作成する必要が出てきました。
以下のような構成を仮定しましょう。
├── / 「/」
├── /already-exist-routing 「/already-exist-routing」
|
| // 以下を新規作成
└── /new-routing 「/new-routing」
└── /hello 「/new-routing/hello」
└── /about 「/new-routing/about」
本題
ルーティングの定義
先述の/new-routing/*のルーティングをreact-router(<Routes />と<Route />)で作成する場合、以下のようなルーティング定義が必要です。
ディレクトリ構成(抜粋)
./src/
├── layout
│ ├── Layout.tsx
│ └── parts
│ ├── Footer.tsx
│ ├── Header.tsx
│ └── Main.tsx
├── pages
│ ├── already-exist-routing.tsx
│ ├── index.tsx
│ ├── new-routing
│ │ ├── about.tsx
│ │ └── hello.tsx
│ └── new-routing.tsx
├── router
| └── Router.tsx
└── main.tsx
ルーティングは/router/Router.tsxにて定義しています。
import { type FC } from "react";
import { Route, Routes } from "react-router";
import { Index } from "../pages/index";
import { AlreadyExistRouting } from "../pages/already-exist-routing";
import { NewRouting } from "../pages/new-routing";
import { NewRoutingHello } from "../pages/new-routing/hello";
import { NewRoutingAbout } from "../pages/new-routing/about";
// ルーティング用の定数を定義し、`Array.map`で展開するとよりきれいでしょう。
export const Router: FC = () => (
<Routes>
<Route element={<Index />} path="/" />
<Route element={<AlreadyExistRouting />} path="/already-exist-routing" />
{/* 「/new-routing」配下のネストしたルーティングを定義 */}
<Route element={<NewRouting />} path="/new-routing">
<Route element={<NewRoutingHello />} path="/new-routing/hello" />
<Route element={<NewRoutingAbout />} path="/new-routing/about" />
</Route>
</Routes>
);
以下の記載により、ネストしたルーティングを定義しています。
{/* 「/new-routing」配下のネストしたルーティングを定義 */}
<Route element={<NewRouting />} path="/new-routing">
<Route element={<NewRoutingHello />} path="/new-routing/hello" />
<Route element={<NewRoutingAbout />} path="/new-routing/about" />
</Route>
- 「/new-routing」にアクセスすると、
<NewRouting />が表示- 「/new-routing/hello」にアクセスすると、
<NewRouting />と<NewRoutingHello />が表示- 「/new-routing/about」にアクセスすると、
<NewRouting />と<NewRoutingAbout />が表示
/pages/new-routing/hello.tsx
import { memo, type FC } from "react";
export const NewRoutingHello: FC = memo(() => (
<div>
<h2>「/new-routing/hello」へようこそ!</h2>
</div>
));
/pages/new-routing/about.tsx
import { memo, type FC } from "react";
export const NewRoutingAbout: FC = memo(() => (
<div>
<h2>「/new-routing/about」へようこそ!</h2>
</div>
));
<Outlet />で対応するビューを表示
そして<NewRouting />にて<Outlet />を用いることで、/new-routing/*の画面を表示できるはずです。
Renders the matching child route of a parent route or nothing if no child route matches.
import type { FC } from "react";
import { Link } from "react-router";
import { Outlet } from "@mui/icons-material";
export const NewRouting: FC = () => (
<div>
<div>
<h1>「/new-routing」へようこそ!</h1>
</div>
<div>
<nav>
<ul style={{ listStyle: "none" }}>
<li>
<Link to="/new-routing/about">
「/new-routing/about」
</Link>
</li>
<li>
<Link to="/new-routing/hello">
「/new-routing/hello」
</Link>
</li>
</ul>
</nav>
</div>
<div>
{/* 「/new-routing/*」がここに表示されるはず */}
<Outlet />
</div>
</div>
);
起動してみる
原因
当初、「へーreact-routerってルーティングがうまく定義できていないとアイコン表示するんだ~ すげ~」と思っており、ルーティングの設定周りをデバッグし始めました。
が、おかしいところは見当たらず...
1hほど浪費してしまいました...
...おや、<Outlet />の様子が...
import { Outlet } from "@mui/icons-material";
はい、<Outlet />がreact-routerからではなく、様々なアイコン画像を提供してくれるパッケージである@mui/icons-materialからimportされていました...
ということで、import元をreact-routerに修正すると...
import { Link, Outlet } from "react-router";
はい、正しく/new-routing/helloのビューである<NewRoutingHello />を表示できました。




