I have little problems with my ReactJs app, I'm receiving message like:
./src/components/Navbar/index.js
Line 13:3: 'state' is not defined no-undef
Line 17:3: 'handleClick' is not defined no-undef
I'm beginner with JavaScript and it's seams it's easy fix, I just copied that code from another app where it works.
This is my code:
import React, { useState } from 'react';
import { Layout, Menu, Drawer, Icon } from 'antd';
import { Mobile, Default } from '../Responsive';
import './index.less';
const { Header } = Layout;
const { SubMenu } = Menu;
const Navbar = props => {
state = {
current: 'home',
};
handleClick = e => {
console.log('click ', e);
this.setState({
current: e.key,
});
};
const [visible, setVisible] = useState(false);
const menu = (
<Menu
theme="lite"
mode="horizontal"
defaultSelectedKeys={['2']}
style={{ lineHeight: '64px' }}
onClick={this.handleClick} selectedKeys={[this.state.current]} mode="horizontal">
<Menu.Item key="mail">
<Icon type="mail" />
Navigation One
</Menu.Item>
<Menu.Item key="app" disabled>
<Icon type="appstore" />
Navigation Two
</Menu.Item>
<SubMenu
title={
<span className="submenu-title-wrapper">
<Icon type="setting" />
Navigation Three - Submenu
</span>
}
>
<Menu.ItemGroup title="Item 1">
<Menu.Item key="setting:1">Option 1</Menu.Item>
<Menu.Item key="setting:2">Option 2</Menu.Item>
</Menu.ItemGroup>
<Menu.ItemGroup title="Item 2">
<Menu.Item key="setting:3">Option 3</Menu.Item>
<Menu.Item key="setting:4">Option 4</Menu.Item>
</Menu.ItemGroup>
</SubMenu>
<Menu.Item key="alipay">
<a href="https://ant.design" target="_blank" rel="noopener noreferrer">
Navigation Four - Link
</a>
</Menu.Item>
</Menu>
);
return (
<Header className="app-header">
<Default>{menu}</Default>
<Mobile>
<Icon type="bars" size="large" className="nav-icon" onClick={() => setVisible(true)} />
<Drawer
title=""
placement="left"
closable
onClose={() => setVisible(false)}
visible={visible}
className="nav-drawer"
>
{menu}
</Drawer>
</Mobile>
</Header>
);
};
export default Navbar;
I copied this state and handleClick from another app but it was class, I tried to change const Navbar with class NavBar extends Component but no success.
You are mixing react components and react hooks. You should either use hook (useState), or components (this).
Here is your code with hooks
import React, { useState } from 'react';
import { Layout, Menu, Drawer, Icon } from 'antd';
import { Mobile, Default } from '../Responsive';
import './index.less';
const { Header } = Layout;
const { SubMenu } = Menu;
function Navbar(props) {
const [current, setCurrent] = useState('home');
const [visible, setVisible] = useState(false);
function handleClick(e) {
console.log('click ', e);
setCurrent(e.key)
};
const menu = (
<Menu
theme="lite"
mode="horizontal"
defaultSelectedKeys={['2']}
style={{ lineHeight: '64px' }}
onClick={this.handleClick} selectedKeys={[current]} mode="horizontal">
<Menu.Item key="mail">
<Icon type="mail" />
Navigation One
</Menu.Item>
<Menu.Item key="app" disabled>
<Icon type="appstore" />
Navigation Two
</Menu.Item>
<SubMenu
title={
<span className="submenu-title-wrapper">
<Icon type="setting" />
Navigation Three - Submenu
</span>
}
>
<Menu.ItemGroup title="Item 1">
<Menu.Item key="setting:1">Option 1</Menu.Item>
<Menu.Item key="setting:2">Option 2</Menu.Item>
</Menu.ItemGroup>
<Menu.ItemGroup title="Item 2">
<Menu.Item key="setting:3">Option 3</Menu.Item>
<Menu.Item key="setting:4">Option 4</Menu.Item>
</Menu.ItemGroup>
</SubMenu>
<Menu.Item key="alipay">
<a href="https://ant.design" target="_blank" rel="noopener noreferrer">
Navigation Four - Link
</a>
</Menu.Item>
</Menu>
);
return (
<Header className="app-header">
<Default>{menu}</Default>
<Mobile>
<Icon type="bars" size="large" className="nav-icon" onClick={() => setVisible(true)} />
<Drawer
title=""
placement="left"
closable
onClose={() => setVisible(false)}
visible={visible}
className="nav-drawer"
>
{menu}
</Drawer>
</Mobile>
</Header>
);
};
export default Navbar;
Everything else looks fine except:
const [current, setCurrent] = useState('home') ;
const handleClick = e => {
console.log('click ', e);
setCurrent(e.key);
};
Actually you have to convert the this.state to hook as well.
Related
I'm experiencing an issue with the <Link> component from react-router-dom.
The above error occurred in the <Link> component:
at LinkWithRef (http://localhost:3000/react-portfolio/static/js/bundle.js:64573:7)
at button
at http://localhost:3000/react-portfolio/static/js/bundle.js:3642:66
at ButtonBase (http://localhost:3000/react-portfolio/static/js/bundle.js:9678:82)
at http://localhost:3000/react-portfolio/static/js/bundle.js:3642:66
at Button (http://localhost:3000/react-portfolio/static/js/bundle.js:9381:59)
at div
at div
at http://localhost:3000/react-portfolio/static/js/bundle.js:3642:66
at Toolbar (http://localhost:3000/react-portfolio/static/js/bundle.js:20646:82)
at header
at http://localhost:3000/react-portfolio/static/js/bundle.js:3642:66
at Paper (http://localhost:3000/react-portfolio/static/js/bundle.js:18055:82)
at http://localhost:3000/react-portfolio/static/js/bundle.js:3642:66
at AppBar (http://localhost:3000/react-portfolio/static/js/bundle.js:8771:83)
at div
at http://localhost:3000/react-portfolio/static/js/bundle.js:3642:66
at Box (http://localhost:3000/react-portfolio/static/js/bundle.js:23577:72)
at div
at Navbar (http://localhost:3000/react-portfolio/static/js/bundle.js:629:5)
at div
at PortfolioContainer (http://localhost:3000/react-portfolio/static/js/bundle.js:1060:88)
at div
at App
at Router (http://localhost:3000/react-portfolio/static/js/bundle.js:66149:15)
at BrowserRouter (http://localhost:3000/react-portfolio/static/js/bundle.js:64481:5)
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
logCapturedError # react-dom.development.js:18687
I'm guessing that this is located in my Navbar file somewhere, which you can see below:
import * as React from 'react';
import AppBar from '#mui/material/AppBar';
import Box from '#mui/material/Box';
import Toolbar from '#mui/material/Toolbar';
import Typography from '#mui/material/Typography';
import Button from '#mui/material/Button';
import { Link } from 'react-router-dom';
import IconButton from '#mui/material/IconButton';
import Menu from '#mui/material/Menu';
import MenuIcon from '#mui/icons-material/Menu';
import MenuItem from '#mui/material/MenuItem';
import '../styles/root.css';
import useWindowDimension from '../utils/windowDimensions';
import About from '../pages/About';
import Contact from '../pages/Contact';
import Portfolio from '../pages/Portfolio';
import Resume from '../pages/Resume';
export default function Navbar({ handlePageChange }) {
const { height, width } = useWindowDimension();
const [anchorEl, setAnchorEl] = React.useState(null);
const open = Boolean(anchorEl);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const [anchorElNav, setAnchorElNav] = React.useState(null);
const openNav = Boolean(anchorElNav);
const handleOpenNavMenu = (event) => {
setAnchorElNav(event.currentTarget);
};
const handleCloseNavMenu = () => {
setAnchorElNav(null);
}
const handleClose = () => {
setAnchorEl(null);
};
return (
<div>
<Box sx={{ flexGrow: 1, width: "100%" }} >
<AppBar position="static" id="navbar">
<Toolbar>
<Typography
id="nav-logo"
variant="h6"
component="div"
sx={{ flexGrow: 1 }}
fontFamily="reklame-script, sans-serif"
fontWeight="700"
fontStyle="normal"
fontSize="36px"
// onClick={() => handlePageChange('About')}
>
My Portfolio
</Typography>
{width >= 900
?
<div
style={{ display: "flex", direction: "row", flexWrap: "wrap", justifyContent: "space-evenly", alignContent: "center", fontWeight: "bold" }}
>
<Button
color="inherit"
onClose={handleClose}
// onClick={() => handlePageChange('About')}
>
<Link to={<About />}>
About Me
</Link>
</Button>
<Button
color="inherit"
onClose={handleClose}
// onClick={() => handlePageChange('Portfolio')}
>
<Link to={<Portfolio />}>
Portfolio
</Link>
</Button>
<Button
color="inherit"
onClose={handleClose}
// onClick={() => handlePageChange('Contact')}
>
<Link to={<Contact />}>
Contact Me
</Link>
</Button>
<Button
color="inherit"
onClose={handleClose}
// onClick={() => handlePageChange('Contact')}
>
<Link to={<Resume />}>
Resume
</Link>
</Button>
</div>
:
// Mobile Hamburger Menu
<Box id='hamburger-menu' sx={{ flexGrow: 1, display: { xs: "flex", md: "none" }, justifyContent: "right" }}>
<IconButton
id="menu-button"
size="large"
aria-controls={openNav ? 'menu-appbar' : undefined}
aria-haspopup="true"
aria-expanded={openNav ? 'true' : undefined}
onClick={handleOpenNavMenu}
color="inherit"
>
<MenuIcon />
</IconButton>
<Menu
id="menu-appbar"
anchorEl={anchorElNav}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'right',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
open={openNav}
onClose={handleCloseNavMenu}
sx={{
display: { xs: 'block', md: 'none' },
}}
>
<div>
<MenuItem className='mobileMenuItem' onClick={handleCloseNavMenu}>
<Button color="inherit" >
<Link style={{ textDecoration: "none", color: "black" }} to="/" onClose={handleClose}>
About Me
</Link>
</Button>
</MenuItem>
<MenuItem className='mobileMenuItem' onClick={handleCloseNavMenu}>
<Button color="inherit" onClose={handleClose}>
<Link style={{ textDecoration: "none", color: "black" }} to={"/portfolio"}>
Portfolio
</Link>
</Button>
</MenuItem>
<MenuItem className='mobileMenuItem' onClick={handleCloseNavMenu}>
<Button color="inherit" onClose={handleClose}>
<Link style={{ textDecoration: "none", color: "black" }} to="/contact">
Contact Me
</Link>
</Button>
</MenuItem>
<MenuItem className='mobileMenuItem' onClick={handleCloseNavMenu}>
<Button color="inherit" onClose={handleClose}>
<Link style={{ textDecoration: "none", color: "black" }} to="/resume">
Resume
</Link>
</Button>
</MenuItem>
<Menu
id="basic-menu"
anchorEl={anchorEl}
open={open}
MenuListProps={{
'aria-labelledby': 'basic-button',
}}
onClick={handleClick}
onClose={handleClose}
>
</Menu>
</div>
</Menu>
</Box>
}
</Toolbar>
</AppBar>
</Box>
</div>
);
}
If it's not there, perhaps it's in my PortfolioContainer file? This can be seen below.
import React, { useState } from "react";
import About from "../pages/About";
import Portfolio from "../pages/Portfolio";
import Contact from "../pages/Contact";
import Resume from "../pages/Resume";
import Navbar from "../components/Navbar";
import Footer from "../components/Footer";
export default function PortfolioContainer() {
const [currentPage, setCurrentPage] = useState('');
const renderPage = () => {
if (currentPage === '/') {
return <About />
}
if (currentPage === '/resume') {
return <Resume />;
}
if (currentPage === '/portfolio') {
return <Portfolio />;
}
if (currentPage === '/contact') {
return <Contact />;
}
// return <About />;
};
const handlePageChange = (page) => setCurrentPage(page);
return (
<div id="portfolioContainer">
<Navbar currentPage={currentPage} handlePageChange={handlePageChange} />
{renderPage()}
<Footer />
</div>
);
};
Thank you in advance for any and all help!
I assumed you are useing react-router-dom#6.6.1 (latest version). "to" prop from component expect a string but you provide the component. That's why you get cyclic object error. I took your code an defined a router in index.js file like this
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import App from "./App";
import Resume from "./Resume";
const router = createBrowserRouter([
{
path: "/",
element: <App />
},
{
path: "/resume",
element: <Resume />
}
]);
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
root.render(
<StrictMode>
<RouterProvider router={router} />
</StrictMode>
);
and in my App.js file I used Link component like this
<Button
color="inherit"
onClose={handleClose}
>
<Link to="/resume">Resume</Link>
</Button>
The issue it seems is that you aren't using react-router to its fullest. The Link component should be specifying a to prop that matches a URL pathname that you are rendering a Route component for. PortfolioContainer should be rendering the routes you are trying to link to from the Navbar component.
Example:
PortfolioContainer
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import About from "../pages/About";
import Portfolio from "../pages/Portfolio";
import Contact from "../pages/Contact";
import Resume from "../pages/Resume";
import Navbar from "../components/Navbar";
import Footer from "../components/Footer";
export default function PortfolioContainer() {
return (
<BrowserRouter>
<div id="portfolioContainer">
<Navbar />
<Routes>
<Route path="/" element={<About />} />
<Route path="/resume" element={<Resume />} />
<Route path="/portfolio" element={<Portfolio />} />
<Route path="/contact" element={<Contact />} />
</Routes>
<Footer />
</div>
</BrowserRouter>
);
};
Navbar
...
<Link to="/">
About Me
</Link>
...
<Link to="/portfolio">
Portfolio
</Link>
...
Here I have an image of the current header render. The headercomprises of a HeaderMenu and 3 Links. The links are working fine, but the HeaderMenu is causing the links to fall below it. HeaderMenu contains a div which wraps a Button and Popper, acting as a dropdown menu.
I'm also not sure if this design structure is correct, but for the styles, I have one styles.js file which I pull from. I then pass these styles down as props to the smaller components for rendering. That's why the components here have a props classes that comes from useStyles in index.js.
Header.js
import { AppBar, Button, Link, Toolbar, Typography } from '#material-ui/core'
import HeaderMenu from './HeaderMenu.js'
const Header = (props) => {
const { classes } = props
return (
<AppBar position="static" color="default" elevation={0} className={classes.appBar}>
<Toolbar className={classes.toolbar}>
<Typography variant="h6" color="inherit" noWrap className={classes.toolbarTitle}>
Company name
</Typography>
<nav>
<HeaderMenu classes={classes}/>
<Link variant="button" color="textPrimary" href="#" className={classes.link}>
Here
</Link>
<Link variant="button" color="textPrimary" href="#" className={classes.link}>
Enterprise
</Link>
<Link variant="button" color="textPrimary" href="#" className={classes.link}>
Support
</Link>
</nav>
<Button href="#" color="primary" variant="outlined" className={classes.link}>
Login
</Button>
</Toolbar>
</AppBar>
)
}
export default Header
HeaderMenu.js
import React from 'react'
import { Button, ClickAwayListener, Grow, Paper, Popper, MenuItem, MenuList } from '#material-ui/core'
const HeaderMenu = (props) => {
const { classes } = props
const [open, setOpen] = React.useState(false)
const anchorRef = React.useRef(null)
const handleToggle = () => {
setOpen((prevOpen) => !prevOpen)
}
const handleClose = (event) => {
if (anchorRef.current && anchorRef.current.contains(event.target)) {
return
}
setOpen(false)
}
function handleListKeyDown (event) {
if (event.key === 'Tab') {
event.preventDefault()
setOpen(false)
}
}
// return focus to the button when we transitioned from !open -> open
const prevOpen = React.useRef(open)
React.useEffect(() => {
if (prevOpen.current === true && open === false) {
anchorRef.current.focus()
}
prevOpen.current = open
}, [open])
return (
<div className={classes.link}>
<Button
ref={anchorRef}
aria-controls={open ? 'menu-list-grow' : undefined}
aria-haspopup="true"
onClick={handleToggle}
>
Details
</Button>
<Popper open={open} anchorEl={anchorRef.current} role={undefined} transition disablePortal>
{({ TransitionProps, placement }) => (
<Grow
{...TransitionProps}
style={{ transformOrigin: placement === 'bottom' ? 'center top' : 'center bottom' }}
>
<Paper>
<ClickAwayListener onClickAway={handleClose}>
<MenuList autoFocusItem={open} id="menu-list-grow" onKeyDown={handleListKeyDown}>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</MenuList>
</ClickAwayListener>
</Paper>
</Grow>
)}
</Popper>
</div>
)
}
export default HeaderMenu
You should wrap all your links into a div and then add this to your <nav></nav>
display: flex;
justify-content: space-evenly;
align-items: center;
This will allow it to stay everything in the same line.
Please apologize my lack of knowledge but I'm new to React and JavaScript.
I'm building a Website where I have a Sidebar and a Navbar on top of the page. The Sidebar is activated / deactivated via an hamburger menu which is located in the Navbar-component. It is activated via CSS-classes: <nav className={isActive ? 'nav-menu active' : 'nav-menu'}>
My Problem now is, that I dont know how to transfer the variables toggleButton and isActive from the Navbar.jsx where they are declared to the Sidebar.jsx where I need them to activate my Sidebar.
Do I need to import the js files? Is it possible to export isActive and toggleButton seperatly from the JSX-Code?
Thanks for your help! :)
This is my Code:
Navbar-component
import React from "react";
import Navbar from "react-bootstrap/Navbar";
import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";
import Nav from "react-bootstrap/Nav";
import FormControl from "react-bootstrap/Form";
import Dropdown from "react-bootstrap/Dropdown";
import './Navbar.css';
const NavbarTop = () => {
const [isActive, setIsActive] = useState(false)
const toggleButton = useCallback(
() => setIsActive(prevState => !prevState),
[],
);
return (
<>
<Navbar className="background-color" variant="light">
<Navbar.Brand href="#home">
<img
src="https://pbs.twimg.com/profile_images/603568605796634624/Nq0nXZZA_400x400.jpg"
width="30"
height="30"
className="d-inline-block align-top"
alt="React Bootstrap logo"
/>
</Navbar.Brand>
<Dropdown>
<Dropdown.Toggle Classname="color" rvariant="success" id="dropdown-basic">
Kategorien
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item href="#/action-1">Bücher</Dropdown.Item>
<Dropdown.Item href="#/action-2">Veranstaltungen</Dropdown.Item>
<Dropdown.Divider />
<Dropdown.Item href="#/action-3">Etwas Posten</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
<Form inline>
<FormControl type="text" placeholder="Search" className="mr-sm-2" />
<Button variant="outline-primary">Search</Button>
</Form>
<Link to='#' className='menu-bars'>
<HamburgerSpring className="Hamburger"
buttonColor="transparent"
barColor="#007466"
buttonWidth={35}
{...{ isActive, toggleButton }}
/>
</Link>
</Animate>
</Navbar>
</>
);
};
export default NavbarTop;
Sidebar-component:
import React, { useState, useCallback } from 'react';
import { Link } from 'react-router-dom';
import { SidebarData } from './SidebarData';
import { IconContext } from 'react-icons';
import {Animate} from 'react-rebound';
import { HamburgerSpring } from 'react-animated-burgers';
import './Sidebar.css';
function Sidebar(isActive, toggleButton) {
return (
<>
<IconContext.Provider value={{ color: 'white' }}>
<nav className={isActive ? 'nav-menu active' : 'nav-menu'}>
<div className='nav-menu-items'>
<ul onClick={toggleButton}>
{SidebarData.map((item, index) => {
return (
<li key={index} className={item.cName}>
<Link to={item.path}>
{item.icon}
<span>{item.title}</span>
</Link>
</li>
);
})}
</ul>
</div>
</nav>
</IconContext.Provider>
</>
);
}
export default Sidebar;
One possible approach is to move the state one level up.
const ParentComponent = () => {
const [isActive, setIsActive] = useState(false)
const toggleButton = useCallback(
() => setIsActive(prevState => !prevState),
[],
);
.....
.....
{/* You can use like this */}
<SideBar isActive={isActive} toggleButton={toggleButton} />
<NavBar isActive={isActive} toggleButton={toggleButton} />
}
Alternatively, you can use the context API to store to hold the state and access it anywhere within the app. In your case, I think the first option is a better idea given it's simple nature.
This is where you'd lift state up, outside of those into a container of sorts.
function Container() {
const [toggleIsActive, setToggleIsActive] = useState(false);
return (
<Navbar ... toggleIsActive={toggleIsActive} setToggleIsActive={setToggleIsActive} />
<Sidebar ... toggleIsActive={toggleIsActive} setToggleIsActive={setToggleIsActive} />
)
}
Essentially you track that from higher up in the tree while providing the values/methods for changing to the children components.
I am using Material-UI for my React project and having issues with getting the drawer to function properly when I add in nested list items. Everything was working great until I added those in. I believe the root cause is that by clicking on the dropdown menu and changing the state of the list item to be open I'm causing the application to re-render. Not sure how to solve this.
Problem: Nested list items close the drawer automatically when you click the top level. The user then has to open the drawer again to see the list items in the drop down.
Desired Functionality: The user clicks the menu item to open the drawer. The user can click on "Leadership Triad" and see the menu items within while the drawer stays open. When the user clicks off, the drawer closes.
Code Sandbox
https://codesandbox.io/s/material-ui-nested-menu-forked-qqdiv
My Code
import React, { useState } from "react";
import { makeStyles } from "#material-ui/core/styles";
import AppBar from "#material-ui/core/AppBar";
import Toolbar from "#material-ui/core/Toolbar";
import Typography from "#material-ui/core/Typography";
import IconButton from "#material-ui/core/IconButton";
import MenuIcon from "#material-ui/icons/Menu";
import Drawer from "#material-ui/core/Drawer";
import List from "#material-ui/core/List";
import Divider from "#material-ui/core/Divider";
import ListItem from "#material-ui/core/ListItem";
import ListItemIcon from "#material-ui/core/ListItemIcon";
import ListItemText from "#material-ui/core/ListItemText";
import InboxIcon from "#material-ui/icons/MoveToInbox";
import HomeIcon from "#material-ui/icons/Home";
import AccountCircle from "#material-ui/icons/AccountCircle";
import ExitToAppIcon from "#material-ui/icons/ExitToApp";
import ExpandLess from "#material-ui/icons/ExpandLess";
import ExpandMore from "#material-ui/icons/ExpandMore";
import PeopleIcon from "#material-ui/icons/People";
import BusinessIcon from "#material-ui/icons/Business";
import Menu from "#material-ui/core/Menu";
import MenuItem from "#material-ui/core/MenuItem";
import { Link as RouterLink } from "react-router-dom";
import Collapse from "#material-ui/core/Collapse";
const useStyles = makeStyles(theme => ({
root: { flexGrow: 1 },
menuButton: { marginRight: theme.spacing(2) },
title: { flexGrow: 1 },
list: { width: 250 },
nested: { paddingLeft: theme.spacing(4) },
}));
const Header = () => {
const [drawerOpen, setDrawerOpen] = useState(false);
const [anchorEl, setAnchorEl] = useState(null);
const [leadershipTriadMenuOpen, setLeadershipTriadMenuOpen] = useState(false);
const handleLeadershipTriadClick = () => {
setLeadershipTriadMenuOpen(!leadershipTriadMenuOpen);
};
const handleClick = event => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const toggleDrawer = () => {
setDrawerOpen(!drawerOpen);
};
const classes = useStyles();
return (
<div className={classes.root}>
<AppBar position="static">
<Toolbar>
<IconButton
edge="start"
className={classes.menuButton}
color="inherit"
aria-label="menu"
onClick={() => toggleDrawer()}
>
<MenuIcon />
<Drawer
anchor="left"
open={drawerOpen}
onClose={() => toggleDrawer()}
>
<div className={classes.list}>
<List>
<ListItem button component={RouterLink} to="/">
<ListItemIcon>
<HomeIcon color="primary" />
</ListItemIcon>
<ListItemText primary="Home" />
</ListItem>
<ListItem
button
onClick={() => handleLeadershipTriadClick()}
>
<ListItemIcon>
<HomeIcon color="primary" />
</ListItemIcon>
<ListItemText primary="Leadership Triad" />
{leadershipTriadMenuOpen ? (
<ExpandLess />
) : (
<ExpandMore />
)}
</ListItem>
<Collapse
in={leadershipTriadMenuOpen}
timeout="auto"
unmountOnExit
>
<List component="div" disablePadding>
<ListItem button className={classes.nested}>
<ListItemIcon>
<HomeIcon />
</ListItemIcon>
</ListItem>
</List>
</Collapse>
<ListItem button>
<ListItemIcon>
<InboxIcon color="primary" />
</ListItemIcon>
<ListItemText primary="Testing" />
</ListItem>
<ListItem button>
<ListItemIcon>
<InboxIcon color="primary" />
</ListItemIcon>
<ListItemText primary="Testing" />
</ListItem>
</List>
<Divider />
<List>
<ListItem
button
component={RouterLink}
to="/admin/companies"
>
<ListItemIcon>
<BusinessIcon color="primary" />
</ListItemIcon>
<ListItemText primary="Companies" />
</ListItem>
<ListItem
button
component={RouterLink}
to="/admin/users"
>
<ListItemIcon>
<PeopleIcon color="primary" />
</ListItemIcon>
<ListItemText primary="Users" />
</ListItem>
</List>
<Divider />
<List>
<ListItem button component={RouterLink} to="/profile">
<ListItemIcon>
<AccountCircle color="primary" />
</ListItemIcon>
<ListItemText primary="Profile" />
</ListItem>
<ListItem button component={RouterLink} to="/logout">
<ListItemIcon>
<ExitToAppIcon color="primary" />
</ListItemIcon>
<ListItemText primary="Logout" />
</ListItem>
</List>
</div>
</Drawer>
</IconButton>
<Typography variant="h6" className={classes.title}>
Leadership Program
</Typography>
<IconButton color="inherit" onClick={handleClick}>
<AccountCircle />
</IconButton>
<Menu
id="admin-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem
component={RouterLink}
to="/profile"
onClick={handleClose}
>
Profile
</MenuItem>
<MenuItem
onClick={handleClose}
component={RouterLink}
to="/logout"
>
Logout
</MenuItem>
</Menu>
</Toolbar>
</AppBar>
</div>
);
};
export default Header;
Have you tried surrounding the IconButton with a ListItemSecondaryAction?
<ListItemSecondaryAction>
<IconButton onClick={handleOnClick}>
{openState ? <ExpandLess /> : <ExpandMore />}
</IconButton>
</ListItemSecondaryAction>
I was trying to do something similar, where a list item had two clickable areas with two different actions: click the ListItem (to go to a page) or click the IconButton (to expand the ListItem) to display nested ListItems. Without this ListItemSecondaryAction, when I would click on a list item, it would both route and expand the ListItem, which was not desirable.
Adding the SecondaryAction separated click actions of the ListItem and the IconButton. The documentation isn't great, so it took me a while to understand the purpose, but it's here.
I have a very simple antd menu which I used following their docs. However, when the submenu opens it is floating (not attached to the main menu) and it really doesn't look good.
How do I fix this?
This is what my code currently looks like:
export function MainMenu () {
return (
<AntdLayout>
<Menu mode='horizontal' theme='dark' style={{ position: 'fixed', zIndex: 1, width: '100%', marginBottom: 100 }}>
<Menu.Item key='home'>
Home
</Menu.Item>
<SubMenu key='submenu' title='SubMenu'>
<Menu.Item key='1'>
Option 1
</Menu.Item>
<Menu.Item key='2'>
Option 2
</Menu.Item>
</SubMenu>
<Menu.Item key='contact'>
Contact
</Menu.Item>
</Menu>
</AntdLayout>
)
}
Here is a screenshot of what it looks like:
As its not adviced because Ant is a design system, you can achieve it by targeting the .ant-menu-submenu > .ant-menu selectors:
/* ./App.css */
.ant-menu-submenu > .ant-menu {
margin-top: -5px;
}
// index.js
import { Layout, Menu } from 'antd';
import 'antd/dist/antd.css';
import './App.css';
function MainMenu() {
return (
<Layout>
<Menu mode="horizontal" openKeys={['submenu']}>
<Menu.Item key="home">Home</Menu.Item>
<Menu.SubMenu
key="submenu"
title="SubMenu"
>
<Menu.Item key="1">Option 1</Menu.Item>
<Menu.Item key="2">Option 2</Menu.Item>
</Menu.SubMenu>
<Menu.Item key="contact">Contact</Menu.Item>
</Menu>
</Layout>
);
}