背景
下記の教材を進めていて、React Routerのv5での記述方法とv7での記述方法で違う部分があったので記述します
エラー内容
Uncaught Error: [DefaultLayout] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>
DefaultLayoutは<Route>コンポーネントではない。<Routes>の下に置けるのは<Route>もしくは<React.Fragment>だけだよ
エラーが出たソースコード
// App.jsx
import { Routes, Route } from 'react-router';
import { Top } from '../components/pages/Top';
import { Users } from '../components/pages/Users';
import { DefaultLayout } from '../components/templates/DefaultLayout';
export const Router = () => {
return (
<Routes>
<DefaultLayout>
<Route path="/" element={<Top />} />
</DefaultLayout>
<Route path="/users" element={<Users />} />
</Routes>
);
};
// DefaultLayout.jsx
import { Footer } from '../atoms/layout/Footer';
import { Header } from '../atoms/layout/Header';
export const DefaultLayout = (props) => {
const { children } = props;
return (
<>
<Header />
{children}
<Footer />
</>
);
};
-
DefaultLayout内ではpropsを利用して、Topページを表示させようとしていた
なぜ<Routes>は<Route>しか受け付けないのか
<Routes>はレンダリング時に子要素のpathやelementなどのpropsを読み取って、ルーティングテーブルを構築している。任意のコンポーネントが子要素に混ざると、このルートマッチングの仕組みが正しく機能しなくなるため、<Route>または<React.Fragment>のみが許可されている
公式ドキュメントでもchildrenの型はNested Route elementsと明記されている
Nested Route elements
んーこれか…笑
どこかに前提知識的な記載がありそうなきもする
正しいソースコード
// App.jsx
import { Routes, Route } from 'react-router';
import { Top } from '../components/pages/Top';
import { Users } from '../components/pages/Users';
import { DefaultLayout } from '../components/templates/DefaultLayout';
export const Router = () => {
return (
<Routes>
<Route element={<DefaultLayout />}>
<Route path="/" element={<Top />} />
</Route>
<Route path="/users" element={<Users />} />
</Routes>
);
};
// DefaultLayout.jsx
import { Outlet } from 'react-router';
import { Footer } from '../atoms/layout/Footer';
import { Header } from '../atoms/layout/Header';
export const DefaultLayout = () => {
return (
<>
<Header />
<Outlet />
<Footer />
</>
);
};
変更点
-
DefaultLayoutコンポーネントもRouteで囲むようにした -
DefaultLayoutではprops.childrenの代わりにOutletを利用して子ルートの内容を表示するようにした-
Outletは、親ルート内でマッチした子ルートのコンポーネントをレンダリングするための専用コンポーネント
-
感想
- ドキュメントの内容を正確に解釈できていなかった…という点は反省
参考