Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

MUI context menu in a list always has reference to the last item

I’m using Material UI for a context menu in a react app. I’ve made a min repro here:

Edit summer-silence-xzxwd3

export default function App() {
  const [contextMenu, setContextMenu] = React.useState(null);

  const myArray = ["item1", "item2", "item3"];

  const handleContextMenu = (event) => {
    event.preventDefault();
    setContextMenu(
      contextMenu === null
        ? {
            mouseX: event.clientX + 2,
            mouseY: event.clientY - 6
          }
        : null
    );
  };

  const editItem = (i) => {
    setContextMenu(null);
    alert(`Editing ${i}`);
  };

  return (
    <div>
      {myArray.map((i) => (
        <div key={i} onContextMenu={handleContextMenu}>
          <Card sx={{ backgroundColor: "gray", m: 2 }}>
            <CardContent>
              <Typography>{i}</Typography>
            </CardContent>
          </Card>
          <Menu
            open={contextMenu != null}
            onClose={() => setContextMenu(null)}
            anchorReference="anchorPosition"
            anchorPosition={
              contextMenu != null
                ? { top: contextMenu.mouseY, left: contextMenu.mouseX }
                : undefined
            }
          >
            <MenuItem onClick={() => editItem(i)}>Edit</MenuItem>
          </Menu>
        </div>
      ))}
    </div>
  );
}

Every time I right-click > "Edit", the alert always shows for the last item ("item3"). In my full app, I can also drag-drop to rearrange these cards and the behavior will still be whatever card is last in the list after the rearrange.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Not sure what I’m doing wrong here. I thought it might be a missing key issue, but I don’t think that’s the case as the only list item with siblings (the div) has a key. Any ideas?

>Solution :

If you inspect your page, you can see that all 3 menus open at the same time, and the last one always receives the click event.

Here is how you can fix your code:

import "./styles.css";
import Card from "@mui/material/Card";
import CardContent from "@mui/material/CardContent";
import Typography from "@mui/material/Typography";
import Menu from "@mui/material/Menu";
import MenuItem from "@mui/material/MenuItem";
import * as React from "react";

export default function App() {
  const [contextMenu, setContextMenu] = React.useState(null);

  const myArray = ["item1", "item2", "item3"];

  const handleContextMenu = (item) => (event) => {
    event.preventDefault();
    setContextMenu(
      contextMenu === null
        ? {
            item,
            mouseX: event.clientX + 2,
            mouseY: event.clientY - 6
          }
        : null
    );
  };

  const editItem = () => {
    alert(`Editing ${contextMenu.item}`);
    setContextMenu(null);
  };

  return (
    <div>
      {myArray.map((i) => (
        <div key={i} onContextMenu={handleContextMenu(i)}>
          <Card sx={{ backgroundColor: "gray", m: 2 }}>
            <CardContent>
              <Typography>{i}</Typography>
            </CardContent>
          </Card>
        </div>
      ))}

      <Menu
        open={contextMenu != null}
        onClose={() => setContextMenu(null)}
        anchorReference="anchorPosition"
        anchorPosition={
          contextMenu != null
            ? { top: contextMenu.mouseY, left: contextMenu.mouseX }
            : undefined
        }
      >
        <MenuItem onClick={editItem}>Edit</MenuItem>
      </Menu>
    </div>
  );
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading