はじめに
UdemyでReactの講座を購入したのだが共通レイアウトを使用する際にReact Router v5における記法だったためReact Router v6ではどう書くのか詰まった。
今回はその方法をまとめる。
問題点
一部のコンポーネント(今回はTopとUser)で共通レイアウトを使用する際v5では以下のような方法だった。
Router.jsx
import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import Layout from './Layout'; // 共通レイアウトコンポーネント
import Top from './Top'; // トップページコンポーネント
import Users from './Users'; // ユーザーページコンポーネント
import NoPage from './NoPage'; // 404ページコンポーネント
export const Router = () => {
return (
<BrowserRouter>
<Switch>
{/* トップページとユーザーページは共通のレイアウトを使用 */}
<Route exact path="/">
<Layout>
<Top />
</Layout>
</Route>
<Route path="/users">
<Layout>
<Users />
</Layout>
</Route>
{/*404ページは共通のレイアウトを使用しない */}
<Route path="*">
<NoPage />
</Route>
</Switch>
</BrowserRouter>
);
};
しかしv6では<Switch>
の代わりに<Routes>
を使用し、共通レイアウトを提供するLayoutコンポーネントは<Outlet>
を使用してネストされた<Route>
の内容を表示する書き方になった。
つまり以下のようになった。
解決策
TopとUserにLayoutコンポーネントで共通レイアウトを適用させたい場合は以下のようにする。
Router.jsx
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Layout from "./Layout"; // 共通レイアウトコンポーネント
import Top from "./Top"; // トップページコンポーネント
import Users from "./Users"; // ユーザーページコンポーネント
import NoPage from "./NoPage"; // 404ページコンポーネント
export const Router = () => {
return (
<BrowserRouter>
<Routes>
{/* 共通のレイアウトを適用するRoute */}
<Route path="/" element={<Layout />}>
<Route index element={<Top />} /> {/* インデックスルート ("/"のパスではTopの内容が表示される)*/}
<Route path="users" element={<Users />} /> {/* /users */}
</Route>
{/* 共通のレイアウトを適用しないRoute */}
<Route path="*" element={<NoPage />} /> {/* その他の全てのパス */}
</Routes>
</BrowserRouter>
);
};
共通コンポーネントでは<Outlet />
を使用する。そうすることによってネストされたコンポーネントの内容が表示される。
Layout.jsx
import { Footer } from "../atoms/layout/Footer";
import { Header } from "../atoms/layout/Header";
import { Outlet } from "react-router-dom";
export const Layout = () => {
return (
<>
<Header /> {/* ヘッダー */}
<Outlet /> {/* ここにネストされたルートの内容(Topの内容)が表示される */}
<Footer /> {/* フッター */}
</>
);
};
終わりに
学習中のためまだまだ把握しきれていないこともあり間違っている場合もあるのでその際はご連絡ください。