Reputation: 53
I am working on a project of web application with react. Where I used material ui for navbar. there is a show more icon on right side for mobile devices. But when I open it the popover opened at left side and showing an error Material-UI: The anchorEl
prop provided to the component is invalid. I want it on top right side. but couldn't do it. What should I do?
Here is the code
import React, { useState } from 'react';
import './Navbar.css'
import { useScrollTrigger, Slide, AppBar, Toolbar, IconButton, makeStyles, Divider, List, ListItem, ListItemIcon, ListItemText, Hidden, Drawer, useTheme, Menu, MenuItem } from '@material-ui/core';
import MenuIcon from '@material-ui/icons/Menu';
import InboxIcon from '@material-ui/icons/MoveToInbox';
import MailIcon from '@material-ui/icons/Mail';
import MoreIcon from '@material-ui/icons/MoreVert';
import Logo from '../../images/logo.png';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faGithub, faLinkedinIn } from '@fortawesome/free-brands-svg-icons';
const drawerWidth = 240;
const useStyles = makeStyles((theme) => ({
toolbar: theme.mixins.toolbar,
grow: {
flexGrow: 1,
},
menuButton: {
marginRight: theme.spacing(2),
},
sectionDesktop: {
display: 'none',
[theme.breakpoints.up('md')]: {
display: 'flex',
},
},
sectionMobile: {
display: 'flex',
[theme.breakpoints.up('md')]: {
display: 'none',
},
},
drawer: {
[theme.breakpoints.up('sm')]: {
width: drawerWidth,
flexShrink: 0,
},
},
drawerPaper: {
width: drawerWidth,
},
}));
const Navbar = (props) => {
const { window } = props;
const classes = useStyles();
const theme = useTheme();
const [mobileOpen, setMobileOpen] = useState(false);
const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = useState(null);
console.log(mobileMoreAnchorEl);
const HideOnScroll = (props) => {
const { children, window } = props;
const trigger = useScrollTrigger({ target: window ? window() : undefined });
return (
<Slide appear={false} direction="down" in={!trigger}>
{children}
</Slide>
)
}
const handleDrawerToggle = () => {
setMobileOpen(!mobileOpen);
};
const isMobileMenuOpen = Boolean(mobileMoreAnchorEl);
const handleMobileMenuClose = () => {
setMobileMoreAnchorEl(null);
}
const handleMobileMenuOpen = (event) => {
setMobileMoreAnchorEl(event.currentTarget);
}
const mobileMenuId = 'primary-search-account-menu-mobile';
const renderMobileMenu = (
<Menu
anchorEl={mobileMoreAnchorEl}
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
id={mobileMenuId}
keepMounted
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
open={isMobileMenuOpen}
onClose={handleMobileMenuClose}
>
<MenuItem>
<IconButton color="inherit">
<FontAwesomeIcon icon={faGithub} />
</IconButton>
</MenuItem>
<MenuItem>
<IconButton color="inherit">
<FontAwesomeIcon icon={faLinkedinIn} />
</IconButton>
</MenuItem>
</Menu>
);
const drawer = (
<div>
<div className={classes.toolbar} />
<Divider />
<List>
{['GitHub', 'Started', 'Send email', 'Drafts'].map((text, index) => (
<ListItem button key={text}>
<ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
</div>
)
const container = window !== undefined ? () => window().document.body : undefined;
return (
<div className={classes.grow}>
<div>
<HideOnScroll {...props}>
<AppBar>
<Toolbar>
<IconButton
edge="start"
className={classes.menuButton}
color="inherit"
aria-label="open drawer"
onClick={handleDrawerToggle}
>
<MenuIcon />
</IconButton>
<img className="logo" src={Logo} alt="" />
<div className={classes.grow} />
<div className={classes.sectionDesktop}>
<a style={{ textDecoration: 'none' }} href="https://github.com/muhidhossain">
<IconButton style={{ color: 'aqua', outline: 'none' }}>
<FontAwesomeIcon icon={faGithub} />
</IconButton>
</a>
<IconButton style={{ color: 'aqua', outline: 'none' }}>
<FontAwesomeIcon icon={faLinkedinIn} />
</IconButton>
</div>
<div className={classes.sectionMobile}>
<IconButton
aria-label="show more"
aria-controls={mobileMenuId}
aria-haspopup="true"
onClick={handleMobileMenuOpen}
color="inherit"
>
<MoreIcon />
</IconButton>
</div>
</Toolbar>
</AppBar>
</HideOnScroll>
{renderMobileMenu}
</div>
<nav className={classes.drawer} aria-label="mailbox folders">
<Hidden smUp implementation="css">
<Drawer
container={container}
variant="temporary"
anchor={theme.direction === 'rtl' ? 'right' : 'left'}
open={mobileOpen}
onClose={handleDrawerToggle}
classes={{ paper: classes.drawPaper }}
ModalProps={{ keepMounted: true }}
>
{drawer}
</Drawer>
</Hidden>
</nav>
</div>
);
};
export default Navbar;
Upvotes: 5
Views: 8442
Reputation: 2122
The HideOnScroll component is creating this issue. For every re-render, the component is recreated. As the anchorel is pointed to the HTML element, which is no longer present it throws an error. If we move the component outside of the Navbar component, the issue will be fixed.
import React, { useState } from 'react';
import './Navbar.css'
import { useScrollTrigger, Slide, AppBar, Toolbar, IconButton, makeStyles, Divider, List, ListItem, ListItemIcon, ListItemText, Hidden, Drawer, useTheme, Menu, MenuItem } from '@material-ui/core';
import MenuIcon from '@material-ui/icons/Menu';
import InboxIcon from '@material-ui/icons/MoveToInbox';
import MailIcon from '@material-ui/icons/Mail';
import MoreIcon from '@material-ui/icons/MoreVert';
import Logo from '../../images/logo.png';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faGithub, faLinkedinIn } from '@fortawesome/free-brands-svg-icons';
const drawerWidth = 240;
const useStyles = makeStyles((theme) => ({
toolbar: theme.mixins.toolbar,
grow: {
flexGrow: 1,
},
menuButton: {
marginRight: theme.spacing(2),
},
sectionDesktop: {
display: 'none',
[theme.breakpoints.up('md')]: {
display: 'flex',
},
},
sectionMobile: {
display: 'flex',
[theme.breakpoints.up('md')]: {
display: 'none',
},
},
drawer: {
[theme.breakpoints.up('sm')]: {
width: drawerWidth,
flexShrink: 0,
},
},
drawerPaper: {
width: drawerWidth,
},
}));
const HideOnScroll = (props) => {
const { children, window } = props;
const trigger = useScrollTrigger({ target: window ? window() : undefined });
return (
<Slide appear={false} direction="down" in={!trigger}>
{children}
</Slide>
)
}
const Navbar = (props) => {
const { window } = props;
const classes = useStyles();
const theme = useTheme();
const [mobileOpen, setMobileOpen] = useState(false);
const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = useState(null);
console.log(mobileMoreAnchorEl);
const handleDrawerToggle = () => {
setMobileOpen(!mobileOpen);
};
const isMobileMenuOpen = Boolean(mobileMoreAnchorEl);
const handleMobileMenuClose = () => {
setMobileMoreAnchorEl(null);
}
const handleMobileMenuOpen = (event) => {
setMobileMoreAnchorEl(event.currentTarget);
}
const mobileMenuId = 'primary-search-account-menu-mobile';
const renderMobileMenu = (
<Menu
anchorEl={mobileMoreAnchorEl}
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
id={mobileMenuId}
keepMounted
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
open={isMobileMenuOpen}
onClose={handleMobileMenuClose}
>
<MenuItem>
<IconButton color="inherit">
<FontAwesomeIcon icon={faGithub} />
</IconButton>
</MenuItem>
<MenuItem>
<IconButton color="inherit">
<FontAwesomeIcon icon={faLinkedinIn} />
</IconButton>
</MenuItem>
</Menu>
);
const drawer = (
<div>
<div className={classes.toolbar} />
<Divider />
<List>
{['GitHub', 'Started', 'Send email', 'Drafts'].map((text, index) => (
<ListItem button key={text}>
<ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
</div>
)
const container = window !== undefined ? () => window().document.body : undefined;
return (
<div className={classes.grow}>
<div>
<HideOnScroll {...props}>
<AppBar>
<Toolbar>
<IconButton
edge="start"
className={classes.menuButton}
color="inherit"
aria-label="open drawer"
onClick={handleDrawerToggle}
>
<MenuIcon />
</IconButton>
<img className="logo" src={Logo} alt="" />
<div className={classes.grow} />
<div className={classes.sectionDesktop}>
<a style={{ textDecoration: 'none' }} href="https://github.com/muhidhossain">
<IconButton style={{ color: 'aqua', outline: 'none' }}>
<FontAwesomeIcon icon={faGithub} />
</IconButton>
</a>
<IconButton style={{ color: 'aqua', outline: 'none' }}>
<FontAwesomeIcon icon={faLinkedinIn} />
</IconButton>
</div>
<div className={classes.sectionMobile}>
<IconButton
aria-label="show more"
aria-controls={mobileMenuId}
aria-haspopup="true"
onClick={handleMobileMenuOpen}
color="inherit"
>
<MoreIcon />
</IconButton>
</div>
</Toolbar>
</AppBar>
</HideOnScroll>
{renderMobileMenu}
</div>
<nav className={classes.drawer} aria-label="mailbox folders">
<Hidden smUp implementation="css">
<Drawer
container={container}
variant="temporary"
anchor={theme.direction === 'rtl' ? 'right' : 'left'}
open={mobileOpen}
onClose={handleDrawerToggle}
classes={{ paper: classes.drawPaper }}
ModalProps={{ keepMounted: true }}
>
{drawer}
</Drawer>
</Hidden>
</nav>
</div>
);
};
export default Navbar;
Upvotes: 4