Steps for successfully sending data to a MenuItem event handlerExplanation on how to

My issue arises when I attempt to render a Menu for each element in an array, as the click handlers for the items only receive the final element in the array rather than the specific element used for that particular render.

The scenario involves having a list of items where each item has a menu to perform actions unique to that individual item, such as "Delete", "Edit", etc.

Example that does not work: 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>
  ));
}

If I maintain a map linking array elements to anchors for the Menu, then it functions as expected.

Example that works: 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>
  ));
}

Is this the correct or intended way to render multiple menus?

Answer №1

When looking at the first example, it becomes clear that all the menus are set to open simultaneously due to sharing the same 'open' prop state. Consequently, only the last item appears as it is positioned on top.

In contrast, the second example functions correctly by accessing the state property for each 'number', allowing only one menu to be 'open' at any given time. This approach serves as a viable solution because as a result of the 'ClickAway' event, a user cannot open multiple menus concurrently.

To address this issue in a straightforward manner, consider implementing the following basic example. Each menu will only be displayed as 'open' when its corresponding number is selected:

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>
  ));
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The POST request functions smoothly in Postman, however, encounters an error when executed in node.js

Just recently I began learning about node.js and attempted to send a post request to an external server, specifically Oracle Commmerce Cloud, in order to export some data. Check out this screenshot of the request body from Postman: View Request Body In Pos ...

Using PHP and JQuery to disable a button after the letter "U" is typed

I am looking for a way to disable the button when the term "U" (defined as Unable) appears. How can I achieve this? Below is the button in question: <input type="submit" class="form-control btn-warning" name="search" value="Search Data"></input& ...

Adjusting the empty image source in Vue.js that was generated dynamically

Currently experimenting with Vue.js and integrating a 3rd party API. Successfully fetched the JSON data and displayed it on my html, but encountering issues with missing images. As some images are absent from the JSON file, I've saved them locally on ...

Guide on developing a Vue modal for transferring user input to a separate component

I have been working on creating a modal component that allows users to input data and then displays it in another component. For example, the user is prompted to enter their first and last name in a modal component (Modal.vue). Once the user saves this inf ...

Can JavaScript be used to determine if any code has been executed from the browser's console?

I'm currently developing a JavaScript game and I want to prevent cheating. Is there a way for me to track and record commands entered in the JavaScript console? Here's a basic outline of what I have in mind: consoleCommands = ""; window.console ...

Explanation of JavaScript code snippet

fnTest = /abc/.test(function () { abc; }) ? /\bchild\b/ : /.*/; I am struggling to comprehend the functionality of this particular javascript snippet. Would someone be able to elaborate on the logic behind this code fragment? ...

Elements with v-for directive failing to display

I am attempting to incorporate a component using v-for. The data source infoTexts is structured as an Object where the locale code serves as the key and the corresponding message is the value. For example: { nl: 'Text in Dutch', fr: &apo ...

Utilizing query parameters as variables in rewrites with Next.js

My goal is to use Next JS to redirect requests from /home?id=123qwert to the new path of /home/123qwert. I'm struggling with extracting the query parameter from the source and using it in the destination. This is what I have attempted so far: as ...

The current context does not have a reference to TextBox

I am encountering an issue with my simple aspx page. Despite not using Master Content Page, I am seeing the following error: The name 'txtFirstName' does not exist in the current context Here is my Markup: <%@ Page Language="C#" %> &l ...

Retrieving the value of a checkbox in a React custom checkbox component

I am facing an issue with my dynamic checkbox functionality. I need to update the state based on the selected options only, but my attempt to filter the state on change is not working as expected. Can someone help me identify what went wrong? const check ...

Using jsdom as a package in a Meteor application is not possible

Recently, I came across an issue with my packages.json file. It looks like this: { "jsdom" : "0.8.0", "request" : "2.25.0" } As part of my project, I have the following code snippet: if (Meteor.isServer) { Meteor.startup(function () { var _ ...

Looking to tally up the rows in a joined table using Sequelize?

In my current project, I am utilizing the sequelize library to interact with a sqlserver database. The database consists of two tables: data: columns - id, name, team, type history:columns - id, node, date, status, data_id (foreignkey) In terms of their ...

Instructions on passing a PHP variable as a parameter to a JavaScript function when a button is clicked

In my implementation of codeigniter 3, I have a view page where the data from $row->poll_question is fetched from the database. The different values within this variable are displayed on the voting.php page. Next to this display, there is a button label ...

Limiting zero is ineffective when it comes to pop-up issues

Hey there, I'm looking to prevent users from inputting zero and dot in a specific field, which is currently working fine. However, when the field is within a pop-up, the code below doesn't seem to work. <script> $('#name').keyp ...

Arrangement of 'const' variables within React Stateless Components

Consider a scenario where I have a straightforward React stateless component: const myComponent = () => { const doStuff = () => { let number = 4; return doubleNumber(number); }; const doubleNumber = number => { ...

Implementing HTMX with just one HTML page: A step-by-step guide

Just starting out with HTMX and created a sample: <!DOCTYPE html> <html> <head> </head> <body> <script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfema ...

Having trouble creating a report with an HTML screenshot using Protractor

Need assistance with generating reports using a html screenshot in Protractor. I have followed all the necessary steps but encountered an error. Any help would be appreciated. Here is my conf.js: // Sample configuration file. var HtmlReporter = require(& ...

MongoDB Integration of Collections - No Data Population

Having trouble merging a client and an account collection. When I use res.send(client), only the account id's are returned. Unsure how to include account information in clients. Have seen one to many solutions, but struggling with this two-way relati ...

Introducing the beta version of Material UI, featuring a dynamic table component with

Utilizing the latest Material-UI react component library, I am attempting to implement a global search feature throughout the entire table. I have attempted to use regex to achieve global and case-sensitive behavior but encountered an error: "match is n ...

Integrating array elements into the keys and values of an object

Given the array below: const Array = ['Michael', 'student', 'John', 'cop', 'Julia', 'actress'] How can I transform it into an object like this? const Object = { Michael: student, John: cop, Juli ...