如何将数据传递给 MenuItem 事件处理程序

时间:2021-02-23 02:32:58

标签: javascript material-ui

当我有一个数组并为数组中的每个元素渲染一个菜单时,项目的点击处理程序只接收数组中的最后一个元素,而不是用于该渲染的元素。

这里的用例是有一个项目列表,其中每个项目都有一个菜单来执行特定于该项目的操作,例如“删除”、“编辑”等。

无效示例:https://codesandbox.io/s/material-demo-forked-u6902?file=/demo.js

export default function SimpleMenu() {
  const [anchor, setAnchor] = React.useState(null);

  const handleOpenMenu = (event) => {
    setAnchor(event.currentTarget);
  };

  const handleCloseMenu = (number) => {
    console.log(number);
    setAnchor(null);
  };

  return ["one", "two"].map((number) => (
    <div key={number}>
      <Button onClick={() => handleCloseMenu(number)}>Log {number}</Button>
      <Button onClick={(e) => handleOpenMenu(e)}>Menu {number}</Button>
      <Menu
        anchorEl={anchor}
        keepMounted
        open={Boolean(anchor)}
        onClose={() => handleCloseMenu(number)}
      >
        <MenuItem onClick={() => handleCloseMenu(number)}>Log Number</MenuItem>
      </Menu>
    </div>
  ));
}

但是,如果我在数组元素的内存中保留一个映射到菜单的锚点,那么它会按预期工作。

工作示例:https://codesandbox.io/s/material-demo-forked-m7utx?file=/demo.js

export default function SimpleMenu() {
  const [anchors, setAnchors] = React.useState({});

  const handleOpenMenu = (number, event) => {
    setAnchors((prevState) => ({
      ...prevState,
      [number]: event.currentTarget
    }));
  };

  const handleCloseMenu = (number) => {
    console.log(number);
    setAnchors((prevState) => ({
      ...prevState,
      [number]: null
    }));
  };

  return ["one", "two"].map((number) => (
    <div key={number}>
      <Button onClick={() => handleCloseMenu(number)}>Log {number}</Button>
      <Button onClick={(e) => handleOpenMenu(number, e)}>Menu {number}</Button>
      <Menu
        anchorEl={anchors[number]}
        keepMounted
        open={Boolean(anchors[number])}
        onClose={() => handleCloseMenu(number)}
      >
        <MenuItem onClick={() => handleCloseMenu(number)}>Log Number</MenuItem>
      </Menu>
    </div>
  ));
}

这是呈现多个菜单的正确或预期方式吗?

1 个答案:

答案 0 :(得分:1)

在您的第一个示例中:由于所有菜单的“打开”属性都处于相同的锚点状态,因此您将同时打开它们。因此,只有最后一项出现,因为它在顶部。

第二个有效,因为您只访问每个“数字”的状态属性,并且一次只有一个菜单是“打开”的。这似乎是一个很好的解决方案,因为由于 'ClickAway' 事件,用户无法打开其他菜单。

这是解决此问题的另一个非常基本的示例。仅当当前选择了菜单编号时,每个菜单才会“打开”。

import React from "react";
import Button from "@material-ui/core/Button";
import Menu from "@material-ui/core/Menu";
import MenuItem from "@material-ui/core/MenuItem";

export default function SimpleMenu() {
  const [anchor, setAnchor] = React.useState(null);
  const [currentNumber, setCurrentNumber] = React.useState(null);

  const handleOpenMenu = (event, number) => {
    setAnchor(event.currentTarget);
    setCurrentNumber(number);
  };

  const handleCloseMenu = (number) => {
    console.log(number);
    setAnchor(null);
    setCurrentNumber(null);
  };

  return ["one", "two"].map((number) => (
    <div key={number}>
      <Button onClick={() => handleCloseMenu(number)}>Log {number}</Button>
      <Button onClick={(e) => handleOpenMenu(e, number)}>Menu {number}</Button>
      <Menu
        anchorEl={anchor}
        keepMounted
        open={currentNumber === number}
        onClose={() => handleCloseMenu(number)}
      >
        <MenuItem onClick={() => handleCloseMenu(number)}>Log {number}</MenuItem>
      </Menu>
    </div>
  ));
}
相关问题