The Complete MUI MenuItem Guide (Links, Disabled, Select, onClick)

The Material-UI MenuItem component has many useful props built into its API. It can easily be given a selected or disabled state, and these states provide useful default classes. The MenuItem component can also be used to add links to Menus.

The MenuItem onClick prop is important for setting states and interacting with Menu links, so we will explore click handling in detail.

Below is the menu we will build. The first MenuItem is a link, the next two are in a selected state, and the final MenuItem is disabled.

MUI MenuItems with links, disabled and selected states
MUI MenuItems with links, disabled and selected states

Full React code is in the Resources section.

A video version of this post is on YouTube or watch below:

MUI MenuItem Links

Material-UI MenuItems can become links by adding two props:

  • component – Passing a Link component makes the MenuItem an anchor element with a potential href value
  • href – The destination to open on click

I also like to add the target prop to make the link open in a new tab.

<MenuItem
  component={Link}
  href="https://en.wikipedia.org/wiki/History_of_the_electric_vehicle"
  target="_blank"
/>

MUI MenuItem Disabled State

The Material-UI MenuItem can be disabled by adding the disabled boolean prop:

<MenuItem
  disabled
/>

This adds the Mui-disabled class in the DOM.

MUI MenuItem Disabled
MUI MenuItem Disabled

This class can be used for targeting disabled MenuItems with nested selectors. I added the below const to each MenuItem sx prop, but it only selected and styled the disabled menu item.

const menuItemStyle = {
    "&.Mui-disabled": {
      backgroundColor: 'lightgrey'
    }
}

MUI MenuItem Selected State

Material-UI MenuItems have a selected boolean that applies default selected styling when the boolean is true.

<MenuItem

  selected
/>

Unfortunately, it is challenging to dynamically update the MenuItem selected state on click of the item. I had to create a complex click handler that maintained an array of MenuItem index values that were selected.

const handleClick = (index: number) => {
  if (selectedList.includes(index)) {
    setSelectedList(
      selectedList.filter(function (value) {
        return value !== index;
      }
      )
    );
  } else {
    setSelectedList([...selectedList, index]);
  }
}

//JSX
<MenuItem
  onClick={() => handleClick(1)}
  selected={selectedList.includes(1)}
/>

I couldn’t find a better way to pass index values to the click handler. If I rendered similar MenuItems from an array using map, I could have passed the map index.

Once selected, the MenuItem had a default class of Mui-selected applied in the DOM. You can use MenuItem classes to style their contents.

MUI MenuItem onClick

The onClick handler for MenuItem typically receives one prop of TypeScript type React.MouseEvent<HTMLLIElement>. This might be slightly different if the component prop was used to change the rendered element type.

Instead of adding a click handler on the individual MenuItems, consider adding the click handler on the wrapping Menu component. The event.target will still contain useful data about the exact MenuItem clicked. In this tutorial I did not use this method because I needed MenuItem index values.

Resources

Useful related posts:

MUI MenuItem API

import { useState } from 'react';
import Button from "@mui/material/Button";
import Menu from "@mui/material/Menu";
import MenuItem from "@mui/material/MenuItem";
import Link from "@mui/material/Link";
import ListItemText from "@mui/material/ListItemText";
import PopupState, { bindTrigger, bindMenu } from "material-ui-popup-state";
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
import ArrowDropUpIcon from "@mui/icons-material/ArrowDropUp";
import { createTheme } from "@mui/material/styles";

export default function SuperMenuItem() {
  const theme = createTheme();
  const [selectedList, setSelectedList] = useState<number[]>([]);

  const handleClick = (index: number) => {
    if (selectedList.includes(index)) {
      setSelectedList(
        selectedList.filter(function (value) {
          return value !== index;
        }
        )
      );
    } else {
      setSelectedList([...selectedList, index]);
    }
  }

  const menuItemBorderBottom = {
    borderBottom: `1px solid ${theme.palette.warning.main}`,
  };

  const menuItemStyle = {
    "&.Mui-disabled": {
      backgroundColor: 'lightgrey'
    },
    "&.Mui-selected": {
      color: 'green'
    }
  }

  return (
    <PopupState variant="popover" popupId="demo-popup-menu">
      {(popupState) => (
        <>
          <Button
            sx={{
              backgroundColor: "warning.main",
              "&:hover": { backgroundColor: "warning.dark" },
            }}
            variant="contained"
            {...bindTrigger(popupState)}
            endIcon={
              popupState.isOpen ? <ArrowDropUpIcon /> : <ArrowDropDownIcon />
            }
          >
            Electric Cars
          </Button>
          <Menu {...bindMenu(popupState)} PaperProps={{ sx: { width: 500 } }}>
            <MenuItem
              onClick={() => handleClick(0)}
              selected={selectedList.includes(0)}
              component={Link}
              href="https://en.wikipedia.org/wiki/History_of_the_electric_vehicle"
              target="_blank"
              sx={{
                ...menuItemBorderBottom,
                color: "primary.main",
                textDecoration: "underline",
                ...menuItemStyle
              }}

            >
              Rivian
            </MenuItem>
            <MenuItem
              onClick={() => handleClick(1)}
              selected={selectedList.includes(1)}
              sx={{
                ...menuItemBorderBottom,
                ...menuItemStyle
              }}
            >
              Prius
            </MenuItem>
            <MenuItem
              onClick={() => handleClick(2)}
              selected={selectedList.includes(2)}
              sx={{...menuItemBorderBottom, ...menuItemStyle}}
            >
              Prologue
            </MenuItem>
            <MenuItem
              onClick={() => handleClick(3)}
              selected={selectedList.includes(3)}
              component={Link}
              disabled
              href="https://www.toyota.com/priusprime/"
              target="_blank"
              sx={{...menuItemStyle}}
            >
              <ListItemText>Leaf</ListItemText>
            </MenuItem>
          </Menu>
        </>
      )}
    </PopupState>
  );
}
Share this post:

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.