Ergun
Ergun

Reputation: 520

MUI anchorEl prop provided is invalid

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

Answers (3)

amota
amota

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

Neil Gaetano Lindberg
Neil Gaetano Lindberg

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

Ergun
Ergun

Reputation: 520

I solved the problem by moving the anchorEl state from parent (Header) component state to local (MobileMenu) component.

Upvotes: 2

Related Questions