Skip to content

Instantly share code, notes, and snippets.

@VesperDev
Last active July 14, 2024 11:50
Show Gist options
  • Save VesperDev/e233115469a6c53bb96443f66385aa22 to your computer and use it in GitHub Desktop.
Save VesperDev/e233115469a6c53bb96443f66385aa22 to your computer and use it in GitHub Desktop.
Sider menu + ant-design + react-router-dom
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import { Layout, Menu, Icon } from 'antd';
import Dashboard from './containers/Dashboard/Dashboard';
import Meseros from './containers/Meseros/Meseros';
const { Header, Content, Footer, Sider } = Layout;
const SubMenu = Menu.SubMenu;
class RouterApp extends Component {
state = {
collapsed: false,
};
onCollapse = (collapsed) => {
this.setState({ collapsed });
}
toggle = () => {
this.setState({
collapsed: !this.state.collapsed,
});
}
render() {
return (
<Router>
<Layout style={{ minHeight: '100vh' }}>
<Sider
collapsible
collapsed={this.state.collapsed}
onCollapse={this.onCollapse}>
<div className="logo" />
<Menu theme="dark" defaultSelectedKeys={['1']} mode="inline">
<Menu.Item key="1">
<Icon type="pie-chart" />
<span>Deshboard</span>
<Link to="/" />
</Menu.Item>
<Menu.Item key="2">
<Icon type="desktop" />
<span>Meseros</span>
<Link to="/meseros" />
</Menu.Item>
</Menu>
</Sider>
<Layout>
<Header style={{ background: '#fff', padding: 0, paddingLeft: 16 }}>
<Icon
className="trigger"
type={this.state.collapsed ? 'menu-unfold' : 'menu-fold'}
style={{ cursor: 'pointer' }}
onClick={this.toggle}
/>
</Header>
<Content style={{ margin: '24px 16px', padding: 24, background: '#fff', minHeight: 280 }}>
<Route exact path="/" component={Dashboard} />
<Route path="/meseros" component={Meseros} />
</Content>
<Footer style={{ textAlign: 'center' }}>
Ant Design ©2016 Created by Ant UED
</Footer>
</Layout>
</Layout>
</Router>
);
}
}
export default RouterApp;
@cjmling
Copy link

cjmling commented Apr 8, 2020

Note above example is based on ant v3 .

In v4 icon have moved have moved, https://ant.design/components/icon/

@cardotrejos
Copy link

I was looking this example! Thanks!

@cdclaw
Copy link

cdclaw commented Apr 20, 2020

this will not work if you change route programmatically.

Any idea how to solve this problem?

@aneopsy
Copy link

aneopsy commented Apr 21, 2020

If you go directly to "/meseros" or refresh the page, the menu key is wrong because it's set to 1 by default. I'm trying to find one way.

Edit: The best way I found is to use withRouter to pass location as a props and use "selectedKeys={[props.location.pathname]}" in Menu when keys are the subpath ex: key="/"

@mahsa-kh
Copy link

Thanks. Helped me a lot!

@JustGAST
Copy link

@aneopsy, thanks for the tip!
I've done more complex routing selection like this.
I have routes: /admin/course/list, /admin/course/edit, /admin/user/list, /admin/user/edit
And match them in selectedRoute function:

const selectedRoute = () => [
    props.location.pathname.replace(/^(\/admin\/\w+)\/.*/, '$1')
];

<Menu
    mode="inline"
    defaultSelectedKeys={['1']}
    defaultOpenKeys={['sub1']}
    style={{ height: '100%', borderRight: 0 }}
    selectedKeys={selectedRoute()}
>
    <SubMenu key="sub1" icon={<LaptopOutlined />} title="Редактирование" >
        <Menu.Item key={`/admin/course`}>
            <Link to={`/admin/course/list`}>Курсы</Link>
        </Menu.Item>
        <Menu.Item key={`/admin/user`}>
            <Link to={`/admin/user/list`}>Пользователи</Link>
        </Menu.Item>
    </SubMenu>
</Menu>                    

@pubuduwanigasekara
Copy link

This is not connected in key

@yogithesymbian
Copy link

yogithesymbian commented Sep 21, 2020

u save my life , thanks brother @VesperDev

          {items.map((item, idx) => (
            <Menu
              theme={this.state.theme}
              onClick={this.handleClick}
              defaultOpenKeys={["sub1"]}
              selectedKeys={[this.state.current]}
              mode="inline"
            >
              <Menu.Item key={idx} tag={RouteNavLink} to={item.to}>
                <Link to={item.to} />
                {item.htmlBefore && (
                  <div
                    className="d-inline-block item-icon-wrapper"
                    dangerouslySetInnerHTML={{ __html: item.htmlBefore }}
                  />
                )}
                {item.title && <span>{item.title}</span>}
                {item.htmlAfter && (
                  <div
                    className="d-inline-block item-icon-wrapper"
                    dangerouslySetInnerHTML={{ __html: item.htmlAfter }}
                  />
                )}
              </Menu.Item>
            </Menu>
          ))}

@cosacak
Copy link

cosacak commented Sep 25, 2020

thanks

@MounsifChr
Copy link

when you click the menu item, the selected status not change, it not works for me.

Use a state where you keep the selected MenuItem "key" attr and write a function to set it whenever you click a MenuItem component.

pass the stored state to the "selectedKeys" attr on Menu component.

@fernandolucchesi
Copy link

fernandolucchesi commented Feb 19, 2021

Leaving my 2 cents, I managed to fix it using the useLocation hook.
Also had to use the path as key for the items, hope it helps someone. :)

import React from 'react';

import { Menu } from 'antd';
import { Link, useLocation } from 'react-router-dom';

const menuItems = [
  {
    name: 'My menu item',
    link: '/my-first-route',
  },
  {
    name: 'My second menu item',
    link: '/my-second-route',
  },
];

export function Menu() {
  const location = useLocation();

  return (
    <Menu selectedKeys={[location.pathname]}>
      {menuItems.map((item) => (
        <Menu.Item key={item.link}>
          <Link to={item.link}>{item.name}</Link>
        </Menu.Item>
      ))}
    </Menu>
  );
}

@Prabhakarkmr0
Copy link

thank you so much this is what I have been looking for

@ingeniousambivert
Copy link

ingeniousambivert commented Mar 24, 2021

@xinghul and @cdclaw did either one of you figure out how to fix it? I am also stuck here.

EDIT: I fixed the problem. Take a look at this repo.

@lghimfus
Copy link

@himanshu2454
Copy link

So I want to implement something like a Step layout, so only after menu in the sider are visited and the form there is validated should the user be allowed to move to another submenu.

image

issue is how to I restrict routes as well as per availability of submenus ??

@tekxau
Copy link

tekxau commented Mar 25, 2022

So helpful!

@haedoang
Copy link

당신은 1004

@joeydqyuan
Copy link

Leaving my 2 cents, I managed to fix it using the useLocation hook. Also had to use the path as key for the items, hope it helps someone. :)

import React from 'react';

import { Menu } from 'antd';
import { Link, useLocation } from 'react-router-dom';

const menuItems = [
  {
    name: 'My menu item',
    link: '/my-first-route',
  },
  {
    name: 'My second menu item',
    link: '/my-second-route',
  },
];

export function Menu() {
  const location = useLocation();

  return (
    <Menu selectedKeys={[location.pathname]}>
      {menuItems.map((item) => (
        <Menu.Item key={item.link}>
          <Link to={item.link}>{item.name}</Link>
        </Menu.Item>
      ))}
    </Menu>
  );
}

thanks a lot

@amed
Copy link

amed commented Jul 18, 2022

The use of nested components is deprecated and will be removed later.

https://ant.design/components/menu/#Usage-upgrade-after-4.20.0

@donev-stan
Copy link

donev-stan commented Aug 3, 2022

warning.js:6 Warning: [antd: Menu] children will be removed in next major version. Please use items instead.

How do I link to a component using items?

@harunkara
Copy link

Hello, I am using history.push to reach some pages after clicking menu items. But the titles of these pages are not in the menu. After using history.push() I send [] into SeleckedKey(). But when I click on one of the menu items that have a submenu on the pages I go to with history.push, it does not open the submenus. This situation is fixed when clicking on a second and different submenu item. I am using vertical as mode and I am getting this error only in mobile view. It works when I make it inline, but I don't want it to be inline as a view. I will be glad if you can help....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment