I have the below ponent as the main layout. When I click on the menu item, I want them to navigate to the home, holiday calendar, and event pages. What can I do with this horizontal menu? The below code shows the main layout wrapped around the above pages. I am using AntD and react-router. this main layout is wrapped around all other routers.
import { Layout, Menu, Button, Avatar, Row, Col, Space, Dropdown } from "antd";
import React, { useState } from "react";
import { Outlet } from "react-router-dom";
const navigation = [
{ label: "Home", key: 1 },
{ label: "Holiday Calendar", key: 2 },
{ label: "Event", key: 3 },
];
const MainLayout = () => {
const [open, setOpen] = useState(false);
const showDrawer = () => {
setOpen(true);
};
const onClose = () => {
setOpen(false);
window.dispatchEvent(new Event("loadHolidayCalander"));
};
const handleLogOut = () => {
localStorage.removeItem("access-token");
};
const menu = (
<Menu
items={[
{
key: "1",
label: <Button onClick={handleLogOut}>Log out</Button>,
},
]}
></Menu>
);
return (
<Layout style={{backgroundColor:"white"}}>
<Row style={{ backgroundColor:"#404140"}}>
<Col
style={{padding:5, margin:0, height:48}}
flex="300px"
>
<a href="/holiday-calander">
<img src="/logo.png" alt="logo" style={{ height: 38 }} />
</a>
</Col>
<Col>
<Menu
theme="dark"
mode="horizontal"
defaultSelectedKeys={["2"]}
items={navigation}
/>
</Col>
<Col
flex="auto"
style={{
padding:5
}}
>
<div style={{ position: "absolute", right: "5px" }}>
<Space size={20}>
<Dropdown overlay={menu} placement="topRight" arrow>
<Avatar style={{ width: 38, height:38 }} />
</Dropdown>
</Space>
</div>
</Col>
</Row>
<Layout
style={{
padding: 0,
backgroundColor: "white",
marginLeft:28,
marginRight:28,
}}
>
<Outlet />
</Layout>
</Layout>
);
};
export default MainLayout;
I have the below ponent as the main layout. When I click on the menu item, I want them to navigate to the home, holiday calendar, and event pages. What can I do with this horizontal menu? The below code shows the main layout wrapped around the above pages. I am using AntD and react-router. this main layout is wrapped around all other routers.
import { Layout, Menu, Button, Avatar, Row, Col, Space, Dropdown } from "antd";
import React, { useState } from "react";
import { Outlet } from "react-router-dom";
const navigation = [
{ label: "Home", key: 1 },
{ label: "Holiday Calendar", key: 2 },
{ label: "Event", key: 3 },
];
const MainLayout = () => {
const [open, setOpen] = useState(false);
const showDrawer = () => {
setOpen(true);
};
const onClose = () => {
setOpen(false);
window.dispatchEvent(new Event("loadHolidayCalander"));
};
const handleLogOut = () => {
localStorage.removeItem("access-token");
};
const menu = (
<Menu
items={[
{
key: "1",
label: <Button onClick={handleLogOut}>Log out</Button>,
},
]}
></Menu>
);
return (
<Layout style={{backgroundColor:"white"}}>
<Row style={{ backgroundColor:"#404140"}}>
<Col
style={{padding:5, margin:0, height:48}}
flex="300px"
>
<a href="/holiday-calander">
<img src="/logo.png" alt="logo" style={{ height: 38 }} />
</a>
</Col>
<Col>
<Menu
theme="dark"
mode="horizontal"
defaultSelectedKeys={["2"]}
items={navigation}
/>
</Col>
<Col
flex="auto"
style={{
padding:5
}}
>
<div style={{ position: "absolute", right: "5px" }}>
<Space size={20}>
<Dropdown overlay={menu} placement="topRight" arrow>
<Avatar style={{ width: 38, height:38 }} />
</Dropdown>
</Space>
</div>
</Col>
</Row>
<Layout
style={{
padding: 0,
backgroundColor: "white",
marginLeft:28,
marginRight:28,
}}
>
<Outlet />
</Layout>
</Layout>
);
};
export default MainLayout;
Share
Improve this question
edited Nov 6, 2022 at 19:00
Drew Reese
203k17 gold badges237 silver badges268 bronze badges
asked Nov 6, 2022 at 18:34
DmapDmap
1991 gold badge6 silver badges21 bronze badges
3 Answers
Reset to default 7You can add an onClick
handler to the Menu
ponent, which will be passed an object with the key
property you can search the navigation
array for the matching element.
Add a link target to the navigation
array elements.
import { ..., useNavigate, ... } from 'react-router-dom';
...
const navigation = [
{ label: "Home", key: 1, target: "/" },
{ label: "Holiday Calendar", key: 2, "/holidaycalendar" },
{ label: "Event", key: 3, "/event" },
];
...
const navigate = useNavigate();
const handleMenuClick = ({ key }) => {
const { target } = navigation.find(item => item.key === key) || {};
if (target) {
navigate(target);
}
};
...
<Menu
theme="dark"
mode="horizontal"
defaultSelectedKeys={["2"]}
items={navigation}
onClick={handleMenuClick}
/>
An improvement could be to make the key
property the link target.
import { ..., useNavigate, ... } from 'react-router-dom';
...
const navigation = [
{ label: "Home", key: "/" },
{ label: "Holiday Calendar", key: "/holidaycalendar" },
{ label: "Event", key: "/event" },
];
...
const navigate = useNavigate();
const handleMenuClick = ({ key }) => {
if (key) {
navigate(key);
}
};
...
<Menu
theme="dark"
mode="horizontal"
defaultSelectedKeys={["/holidaycalendar"]}
items={navigation}
onClick={handleMenuClick}
/>
Actually you can pass Link
ponent from rrd to label
property in Menu.item
as state in this link.
Example :
import {Link} from 'react-router-dom';
...
items = [
{
key: '/home',
label: <Link to='/home'>Home</Link>,
icon: <SomeIcon />,
},
{
key: '/menu',
label: 'This is parent menu',
icon: <SomeIcon />,
children: [
{
key: '/menu-1',
label: '<Link to='/menu-1'>Sub Menu 1</Link>,
icon: <MenuIcon1 />,
},
{
key: '/menu-2',
label: '<Link to='/menu-2'>Sub Menu 2</Link>,
icon: <MenuIcon2 />,
},
},
]
If you're using React Router 6, you can set id for each of your routes and use it to match it to the correct Menu item.
import { useLocation, matchRoutes, createBrowserRouter } from 'react-router-dom';
...
const routes = [
{ id: 'layout', path: '/', element, children: [
{ id: 'home', index: true, element },
...
] },
...
];
const router = createBrowserRouter(routes);
...
const currentRoutes = matchRoutes(routes, location);
const currentRoutesIds = currentRoutes?.map((r) => r.route.id);
...
const items = [
{
key: 'home',
label: <NavLink to="/">Home</NavLink>,
},
{
key: 'other',
label: <NavLink to="/other">Some other route</NavLink>,
},
...
];
...
<Menu
selectedKeys={currentRoutesIds}
items={items}
/>