はじめに
前回の記事の続きです。
ReactRouterの機能について引き続きまとめていきます。
今回はネストされたルート(Nested Routes)について扱います。
今までは付け焼き刃の知識で実装していたんだな、ということが前回の記事を通してわかったので、しっかりした知識を身につけられるようにします。
事前準備
こちらの環境構築が完了している前提です。
それに加えて、わかりやすいように見た目を整えておきたいので、styled-components
をインストールします。
作成したプロジェクトをVS Codeで開いて、ターミナルから以下のコマンドを入力します。
npm install styled-components
インストールが完了次第、以降の工程に進みます。
そもそもネストされたルートとは
URLのパスの構造と、コンポーネントの階層構造を一致させることができる機能です。
ただ、文字だけだと直感的にわかりにくいので、実際に手を動かしながら確認します。
ネストされたルートを試す
どのような見た目になるか
先に完成形を確認します。
このページの構成として
メニュー
└設定
└通知
のような階層構造になっています。
また、URLを確認すると
ルートパス/settings/notification
になっています。
これがネストされたルートです。
URLのパスの階層構造と、ページ(コンポーネント)の階層構造が一致しているので、作りとしてわかりやすいものになっています。
ReactRouterを使ってどのように実装するのかを見ていきます。
実際に作ってみる
特にポイントのないコンポーネントについては、冗長になるので以下から確認してください。
その他のコンポーネントを確認する
const Notification = () => {
return (
<>
<h1>通知</h1>
</>
);
};
export default Notification;
const Mail = () => {
return (
<>
<h1>メール</h1>
</>
);
};
export default Mail;
上記2つは設定ページのコンポーネントに紐づけます。
const Customer = () => {
return (
<>
<h1>顧客情報</h1>
</>
);
};
export default Customer;
これはホームのコンポーネントに紐づけます。
子コンポーネントの描画を設定
ポイントは2つあります。
まず、親となるコンポーネントにおいて、子コンポーネントを描画するためのコンポーネントを設定することです。
設定ページのコンポーネントを見てみます。
import { Link, Outlet } from "react-router-dom";
import styled from "styled-components";
// スタイルの定義
const SettingsLayout = styled.div`
display: flex;
flex-flow: column;
`;
const TopNav = styled.nav`
width: 70vw;
border-bottom: 1px double gray;
`;
const TopNavUl = styled.ul`
display: flex;
list-style-type: none;
padding: 0px;
`;
const TopNavLi = styled.li`
margin-right: 10px;
`;
// 設定ページのコンポーネント
const Settings = () => {
return (
<SettingsLayout>
<h1>設定情報</h1>
<TopNav>
<TopNavUl>
<TopNavLi>
<Link to="notification">通知</Link>
</TopNavLi>
<TopNavLi>
<Link to="mail">メールアドレス</Link>
</TopNavLi>
</TopNavUl>
</TopNav>
{/* 子コンポーネントを描画する */}
<Outlet />
</SettingsLayout>
);
};
export default Settings;
ごちゃごちゃいろいろ書いていますが、大半はスタイルのための定義なのでおいておきます。
大事なのはOutlet
コンポーネントです。
このコンポーネントは親子関係のある構造の親コンポーネントの方に定義します。
Outlet
コンポーネントを定義した部分に、子コンポーネントが描画されます。
なお、現時点では親子関係の定義はしていません。
これはまた別のところで実施します。
Link
コンポーネントは設定されたパスに飛ばすリンクを生成するだけなので、親子関係の定義とは関係ありません。
ホームのページのコンポーネントにも同様にOutlet
コンポーネントを定義します。
ポイントは同一なので、実際のコードは以下から確認してください。
ホームのコンポーネントを確認する
import { Link, Outlet } from "react-router-dom";
import styled from "styled-components";
// スタイルの定義
const HomeLayout = styled.div`
display: flex;
`;
const SideNav = styled.nav`
width: 150px;
height: 100vh;
border-right: 1px solid gray;
margin-right: 20px;
`;
const SideNavUl = styled.ul`
list-style-type: none;
padding: 0px;
`;
const SideNavLi = styled.li`
margin-bottom: 10px;
`;
// ホームのページのコンポーネント
const Home = () => {
return (
<HomeLayout>
<SideNav>
<h1>メニュー</h1>
<SideNavUl>
<SideNavLi>
<Link to="customer">顧客</Link>
</SideNavLi>
<SideNavLi>
<Link to="settings">設定</Link>
</SideNavLi>
<SideNavLi>
<Link to="/">ホームへ戻る</Link>
</SideNavLi>
</SideNavUl>
</SideNav>
{/* 子コンポーネントを描画する */}
<Outlet />
</HomeLayout>
);
};
export default Home;
親子関係の設定
次に、main.tsx
を以下のように書き換えます。
import React from "react";
import ReactDOM from "react-dom/client";
import {
RouteObject,
RouterProvider,
createBrowserRouter,
} from "react-router-dom";
import Home from "./Home.tsx";
import Customer from "./Customer.tsx";
import Settings from "./Settings.tsx";
import Notification from "./Notification.tsx";
import Mail from "./Mail.tsx";
const routes: RouteObject[] = [
{
path: "/",
element: <Home />,
// Homeコンポーネントの子
children: [
{
path: "customer",
element: <Customer />,
},
{
path: "settings",
element: <Settings />,
// Settingsコンポーネントの子
children: [
{
path: "notification",
element: <Notification />,
},
{
path: "mail",
element: <Mail />,
},
],
},
],
},
];
const router = createBrowserRouter(routes);
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>
);
基本的な作りは前回の記事と変わりません。
ルート情報のオブジェクトに新しくchildren
というプロパティを追加しています。
これが親子関係の設定になります。
customer
とsettings
のパスは/
のパスのchildren
に定義されています。
よって、/customer
、/settings
にアクセスされたとき、それぞれのコンポーネントを描画するという設定になります。
ここでのコンポーネントの描画位置はOutlet
コンポーネントを設定した場所です。
ネストを深くすることもできます。
settings
にはさらにchildren
を設定しています。
これにより、/settings/notification
、/settings/mail
にアクセスされたとき、それぞれのコンポーネントを描画します。
改めて完成形を確認
「設定」のリンクを押下するとsettings
へ遷移するため、設定ページが表示されます。
しかし、それ以上は何も表示されません。
設定ページの「通知」をクリックすると、設定情報のページに、さらに通知ページが表示されます。
このように、children
プロパティで親子関係を設定し、親コンポーネントにOutlet
コンポーネントを設定することで、指定のパスにアクセスされたとき子コンポーネントを描画することができます。
まとめ
ReactRouterの公式ページから重要と思われる2つの機能を取り上げて紹介しました。
なんとなくクライアントサイドルーティングできるものとして使っていましたが、その使い方や機能の豊富さに驚きました。
時間はかかりますが、公式サイトから基礎的な理解を深め、実践に持っていけるように日々意識したいと思いました。