javascriptreactjsreact-routerreact-router-domantd

How to add react routing to AntD horizontal Menu?


I have the below component 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;



Solution

  • You can add an onClick handler to the Menu component, 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}
    />