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 imported path is not found in Tsconfig

Hey there! I've been working on getting my project's imports to play nice with typescript import paths. Every time I encounter this error : Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'app' imported from dist/index.js It seems l ...

What steps should be taken to resolve the error message "This Expression is not constructable"?

I'm trying to import a JavaScript class into TypeScript, but I keep getting the error message This expression is not constructable.. The TypeScript compiler also indicates that A does not have a constructor signature. Can anyone help me figure out how ...

Struggling to access the properties of a Material-UI Button

import * as React from "react"; import { styled } from "@mui/material/styles"; import MuiButton from "@mui/material/Button"; import Slider from "@mui/material/Slider"; interface Props { type: "primary" | ...

Optimal utilization of JSON in JavaScript API: Enhancing Performance, Reinforcing Maintainability, and Optimizing Resources

Currently, I am working on developing an application using Laravel and VueJS (along with Vuex). Although I do not have much experience in working with these frameworks or front-ends, I am curious to know the best practices for utilizing the data received f ...

Using Angular's ng-repeat to iterate through an array and display its objects within another array

One of my tasks involves retrieving json objects through a simple post method. The json contains multiple campaigns, organized in an array structure. Each campaign holds slots, which are also arrays with one or more base_image elements. My goal is to di ...

Adding rows to a Datatable using an object array in rows.add()

Attempting to refresh my current Datatable by fetching new data using an Ajax function. Despite trying various solutions from other sources, the table does not update as expected. The function being used is shown below: $.ajax({ url: "<?php echo s ...

Having trouble adjusting the refresh timer based on user focus with setTimeout

For the past few days, I've been utilizing an ajax call to dynamically refresh specific elements of my webapp every 5 seconds. The implementation with setInterval(refreshElements, 5000) worked perfectly fine. However, now I am considering whether the ...

I possess a function that can retrieve the key of an Object, but now I am faced with the task of accessing the actual Object using this value in JavaScript

This is my first time seeking advice on a technical issue. I'm currently working with the following function: export function sendRequest<T>(req: RawRequest, options) { const start = Date.now(); const reqOptions: CoreOptions = { ...

When the component is initialized, the computed property is not being evaluated

My maps component initializes a Google map, adds markers based on props passed from the parent, and sets the correct bounds of the map. However, the markers are added through a computed property to make it reactive. Everything seems to be working fine, exc ...

Invoke cloud functions independently of waiting for a response

Attempting a clever workaround with cloud functions, but struggling to pinpoint the problem. Currently utilizing now.sh for hosting serverless functions and aiming to invoke one function from another. Let's assume there are two functions defined, fet ...

Automating the selection of a drop down based on a condition in Angular 2: A step-by-step guide

I'm facing an issue with a drop-down menu where no default value is selected. On my homepage, I need to automatically select an option based on query parameters. I've attempted various methods but none have been successful. Below is the code snip ...

Customizing the appearance of charts in AngularJS using the Chart.js

I just started experimenting with AngularJS and recently created a horizontal bar chart using Chart.js and HTML. My next step is to make the chart dynamically appear on the page with the help of AngularJS. Can someone please provide some guidance on how I ...

Asynchronous waterfall call in Node.js to call the method before

Is it possible to invoke a previous method within async.waterfall from a subsequent method? async.waterfall([ function (callback) { }, function (reservationStatus, callback) { }, function (reservationStatusList, f ...

Using Firebase with Arrays in Javascript

Currently, my team and I are working on a project using Firebase with Vue.js as the framework. We've come across a challenge regarding creating, updating, and deleting elements in a Firebase cloud document. For instance, within our 'people&apos ...

What is the best way to showcase an item from an array using a timer?

I'm currently working on a music app and I have a specific requirement to showcase content from an array object based on a start and duration time. Here's a sample of the data structure: [ { id: 1, content: 'hello how are you', start: 0 ...

Issue: Unable to 'locate' or 'access' ./lib/React folder while utilizing webpack

I've been delving into the world of React for a while now and decided to experiment with integrating it with webpack. Below is my webpack.config.js : var path = require('path'); module.exports = { entry: './app.js', outp ...

Tips on creating a unique d3js tree design

I am a beginner when it comes to d3js and javascript in general. My goal is to create an interactive IP administration overview using d3js by modeling json data. I know that the key tool for this job is likely d3.layout.tree, which will provide me with the ...

What is the best way to attach functions to specific jQuery objects and exclude others?

Imagine having an unordered list <ul>: <ul class="products"> ... </ul> You want to use jQuery to select it and then add custom functions to that specific object. For instance, you wish to include an addProduct(productData) function ...

Hiding a parent DIV in JS based on specific content: Here's how

I need help figuring out how to hide multiple parent DIVs based on the content of a specific child DIV. Here's an example: <div class="report-per-day"> <div class="report-day">26 May 2022</div> <div class=" ...

Please refrain from submitting the form until the slow AJAX jQuery process has finished

My form is experiencing a delay of almost 4 seconds due to the Ajax jQuery I am using, which creates fields within the form. This delay causes some users to submit the form before the necessary fields are created. I need a way to prevent the form from bein ...