この投稿では、Ant Designの<Menu>
コンポーネントとNext.jsのルーターを統合して、次のことができるようにする方法を説明します。
- サイドバーのメニューをクリックしたときに、Next.jsのルーターを使って画面遷移できるようにする
- 現在アクセス中のURLに応じてメニューをハイライトする
次の動画のような振る舞いを作っていきます。
このチュートリアルは、
の続きです。
このチュートリアルで作ったプログラムの完成形はGitHubにアップしてあります。
実装後の動作デモはVercelにて見れます。
Next.jsのルーターにAnt Designのメニューと統合する手順
まず、管理画面レイアウトAdminLayout
が全ページで適用されるようにしたいので、index.tsx
から_app.tsx
に移動します:
pages/_app.tsx
import "../styles/globals.css";
import type { AppProps } from "next/app";
import "antd/dist/antd.css";
import dynamic from "next/dynamic";
const AdminLayout = dynamic(() => import("../layouts/adminLayout"), {
ssr: false,
});
export default function MyApp({ Component, pageProps }: AppProps) {
return (
<AdminLayout>
<Component {...pageProps} />
</AdminLayout>
);
}
次に、AdminLayoutのメニューにNext.jsのルーターを組み込んでいきます:
// layouts/adminLayout.tsx
import {
DashboardOutlined,
LaptopOutlined,
MenuFoldOutlined,
MenuUnfoldOutlined,
UserOutlined,
} from "@ant-design/icons";
import { Layout, Menu } from "antd";
import Link from "next/link";
import { useRouter } from "next/router";
import { ReactNode, useState } from "react";
import styles from "./adminLayout.module.css";
const { Header, Sider, Content } = Layout;
export default function AdminLayout({
children,
}: {
readonly children: ReactNode;
}) {
const [collapsed, setCollapsed] = useState<boolean>(false);
const router = useRouter();
function toggle() {
setCollapsed(!collapsed);
}
return (
<Layout>
<Sider trigger={null} collapsible collapsed={collapsed}>
<div className={styles.logo} />
<Menu theme="dark" mode="inline" selectedKeys={[router.pathname]}>
<Menu.Item key="/" icon={<DashboardOutlined />}>
<Link href="/">ダッシュボード</Link>
</Menu.Item>
<Menu.Item key="/users" icon={<UserOutlined />}>
<Link href="/users">利用者</Link>
</Menu.Item>
<Menu.Item key="/equipments" icon={<LaptopOutlined />}>
<Link href="/equipments">備品</Link>
</Menu.Item>
</Menu>
</Sider>
<Layout className="site-layout">
<Header className={styles.siteLayoutBackground} style={{ padding: 0 }}>
{collapsed ? (
<MenuUnfoldOutlined className={styles.trigger} onClick={toggle} />
) : (
<MenuFoldOutlined className={styles.trigger} onClick={toggle} />
)}
</Header>
<Content
className={styles.siteLayoutBackground}
style={{
margin: "24px 16px",
padding: 24,
minHeight: 280,
}}
>
{children}
</Content>
</Layout>
</Layout>
);
}
ポイントとしては、
-
<Menu>
コンポーネントのselectedKeys
に現在ページのpathname
を与えるようにする -
<Menu.Item>
内のchildrenは、next/link
の<Link>
コンポーネントにする
です。
あとは、3つの画面を実装していきます:
// pages/index.tsx
export default function Home() {
return "ダッシュボード";
}
// pages/users.tsx
export default function Users() {
return "利用者";
}
// pages/equipments.tsx
export default function Equipments() {
return "備品";
}
これでAnt DesignのメニューとNext.jsのRouterが統合できました。
冒頭の動画ように、URLとメニューが連動するような動作になっているはずです。