Reputation: 520
I am trying to code a mobile menu, where when the user clicks on the menu icon, the menu is displayed.
I have the following code:
const StyledMenu = withStyles({
paper: {
border: '1px solid #d3d4d5',
},
})((props, ref) => (
<Menu
elevation={0}
getContentAnchorEl={null}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center',
}}
{...props}
/>
))`
and the component:
export default function Header(props) {
const [state, setState] = useState({ mobileView: true, drawerOpen: false, anchorEl: null, openItem: null })
const { mobileView, drawerOpen, anchorEl } = state
const classes = useStyles()
useEffect(() => {
const setResponsiveness = () => {
return window.innerWidth < 900
? setState((prevState) => ({ ...prevState, mobileView: true }))
: setState((prevState) => ({ ...prevState, mobileView: false }));
};
setResponsiveness();
window.addEventListener("resize", () => setResponsiveness());
return () => {
window.removeEventListener("resize", () => setResponsiveness());
}
}, []);
const MobileMenu = (props) => {
const handleClick = (id) => {
if (state.openItem === id) {
setState((prevState) => ({ ...prevState, openItem: null }))
} else {
setState((prevState) => ({ ...prevState, openItem: id }))
}
}
const handleDrawerOpen = (event) =>
setState((prevState) => ({ ...prevState, drawerOpen: true, anchorEl: event.currentTarget }));
const handleDrawerClose = () =>
setState((prevState) => ({ ...prevState, drawerOpen: false }));
return (
<Toolbar>
<IconButton
{...{
edge: "start",
color: "inherit",
"aria-label": "menu",
"aria-haspopup": "true",
variant: "contained",
onClick: handleDrawerOpen,
}}
>
<MenuIcon className={classes.menuIcon} fontSize='40px' />
</IconButton>
<StyledMenu
{...{
id: 'custom-menu',
anchor: "left",
open: drawerOpen,
onClose: handleDrawerClose,
anchorEl: anchorEl
}}
>
<List component='nav' className={classes.appMenu} disablePadding>
{menuItems.map((item, index) => {
const hasSubMenus = item.hasOwnProperty('subMenus')
const ListItemLink = () => {
return (
<ListItem key={index} button component={Link} to={item.link} className={classes.menuItem}>
<ListItemText>{item.label}</ListItemText>
</ListItem>
)
}
const ListItemToggle = () => (
<ListItem key={index} button onClick={() => handleClick(index)} className={classes.menuItem}>
<ListItemText>{item.label}</ListItemText>
{index === state.openItem ? <IconExpandLess /> : <IconExpandMore />}
</ListItem>
)
return (
<React.Fragment key={index}>
{!hasSubMenus ? <ListItemLink /> :
<>
<ListItemToggle />
<Collapse in={index === state.openItem} timeout='auto' className={classes.collapseWrapper}>
<div className={classes.collapseDiv}>
<Divider />
<List component='div' disablePadding>
{item.subMenus.map((el, key) => (
<ListItem key={key} button component={Link} to={el.link} className={classes.menuItem}>
<ListItemText inset>{el.label}</ListItemText>
</ListItem>
))}
</List>
</div>
</Collapse>
</>
}
</React.Fragment>
)
})}
</List>
</StyledMenu>
<Logo />
</Toolbar>
)
}
When the clicking on the button, I get the following error:
React does not recognize the getContentAnchorEl
prop on a DOM element.
MUI: The anchorEl
prop provided to the component is invalid.
The anchor element should be part of the document layout.
Make sure the element is present in the document or that it's not display none.
Upvotes: 3
Views: 9881
Reputation: 331
For future people, if you're wrapping your AppBar in a HideOnScroll/Slide component, that can be the source of the issue (and it was for me). Getting rid of that makes the anchorEl work as expected.
See related question/solution here: Material Ui popover is not on right position
Upvotes: 1
Reputation: 2935
I had the same error message and took the hint, "Make sure the element is present in the document or that it's not display none."
First I was looking on SO when I found this question. I've a similar, but different use case with the @mui/system
to show/hide different navigation using <Box sx={{
. I'm sharing the way I got rid of the same error you report. I was using display: none
, so that in changing from lg
to md
the anchorEl was nested within a parent element that was indeed set to display none (like the error message suggests).
To get rid of display: none
I used visibility along with width to collapse like so:
return (
<List id="id-nav" component="nav" className={classes.root}>
<Box sx={{
display: {
lg: 'inherit'
},
visibility: {
sm: 'hidden',
md: 'hidden',
lg: 'visible'
},
width: {
sm: 0,
md: 0,
lg: 'auto'
},
}}
>
{largeNav}
</Box>
<Box sx={{
display: {
sm: 'inherit',
md: 'inherit'
},
visibility: {
sm: 'visible',
md: 'visible',
lg: 'hidden'
},
width: {
sm: 'auto',
md: 'auto',
lg: 0
}
}}
>
{mediumNav}
</Box>
</List>
);
Upvotes: 1
Reputation: 520
I solved the problem by moving the anchorEl state from parent (Header) component state to local (MobileMenu) component.
Upvotes: 2