The issue I am facing is that the map function is not functioning correctly when I click

I am currently working on a project in ReactJs that includes a sidebar with dropdown menu functionality.
Desired Outcome
When I click on an option in the sidebar that has a submenu, it should display that submenu and close upon another click.
Current Issue
At the moment, clicking on any option shows all submenus simultaneously. For instance, selecting "Publications" displays both featured publications and journal publications options at once. How can I resolve this?

The array containing sidebar items

const sidebarItems = [
  {
    title: "Publications",
    url: "#",
    subMenu: [
      {
        title: "Journal Publications",
        url: "#",
      },
      {
        title: "Featured Publications",
        url: "#",
      },
    ],
  },
  {
    title: "Team Members",
    url: "#",
    subMenu: [
      {
        title: "Current Members",
        url: "#",
      },
      {
        title: "Lab Alumni",
        url: "#",
      },
    ],
  },

  {
    title: "Projects",
    url: "#",
    subMenu: [
      {
        title: "Project 1",
        url: "#",
      },
      {
        title: "Project 2",
        url: "#",
      },
      {
        title: "Project 3",
        url: "#",
      },
    ],
  },
  {
    title: "News",
    url: "#",
  },
  {
    title: "Contact Us",
    url: "#",
  },
];

export default sidebarItems;

The Sidebar Component

import { useState } from "react";
import { Box, Text } from "@chakra-ui/react";
import sidebarItems from "./sidebarItems";



export default function Sidebar() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div>
      <Box>
        {sidebarItems.map((items) => {
          return (
            <Box
              width='200px'
              height='40px'
              textAlign='center'
              cursor='pointer'
              onClick={() => {
                setIsOpen(!isOpen);
              }}
            >
              <Text>{items.title}</Text>
              {isOpen
                ? items.subMenu?.map((item) => {
                    return <Text>{item.title}</Text>;
                  })
                : ""}
            </Box>
          );
        })}
      </Box>
    </div>
  );
}

Answer №1

To effectively manage the opening and closing of subMenus, you will need to utilize an array state variable in your code. Currently, your single state variable isOpen is responsible for controlling all subMenus.

           {isOpen
                ? items.subMenu?.map((item) => {
                    return <Text>{item.title}</Text>;
                  })
                : ""}

In order to properly handle each sidebar item's visibility, it is important to have an array state variable that corresponds with each item and controls whether it is open or closed.

const [isOpen, setIsOpen] = useState(Array(sidebarItems.length).fill(false));

Make sure you are updating and manipulating the correct element within the array when setting the value of isOpen.

onClick={() => {
                let newIsOpen = [...isOpen];
                newIsOpen[index] = !isOpen[index];
                setIsOpen(newIsOpen);
              }}

By following these steps, you should be on your way to resolving this issue successfully.

Answer №2

The issue stems from using incorrect logic and failing to specify which submenu should be displayed. To resolve this, begin by removing the current state and refrain from utilizing it. Next, create a new state like so:

const [selectedMenu, setSelectedMenu] = useState("");

Then, define the following function:

const handleClick = (title) => {
    setSelectedMenu(title); 
}

Subsequently, upon clicking on the Box element, invoke the function in this manner:

 onClick={() => handleClick(item.title)}

Finally, structure your logic as follows:

      <Text>{items.title}</Text>
      {item.title === selectedMenu
        ? items.subMenu?.map((item) => {
            return <Text>{item.title}</Text>;
          })
        : ""}

Answer №3

It appears that the issue is arising from the fact that only one state variable is assigned to each sidebar option. To resolve this, consider assigning a unique variable to track whether each submenu should be open or closed.

Looking at your code, it seems that setting the isOpen state variable to true causes all options to display as open due to how the function iterates over them.

Try creating individual variables for each menu option to control whether their respective submenus should be visible or hidden.

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

What is the procedure for invoking a function when the edit icon is clicked in an Angular application

My current Angular version: Angular CLI: 9.0.0-rc.7 I am currently using ag-grid in my project and I encountered an issue when trying to edit a record. I have a function assigned to the edit icon, but it is giving me an error. Error message: Uncaught Re ...

React-router-dom combines the URLs without triggering any rendering

Just starting out with React-router-dom 6^4 library and running into a bit of trouble. I have already set up two simple components (Log In Form and Sign Up Form) using the c-r-a template. According to the documentation, I need to create an instance of Brow ...

Jest is not producing any output at all when executing tests

Below is a snapshot of my package.json: "jest": { "cacheDirectory": "/tmp/jestCache", "scriptPreprocessor": "node_modules/babel-jest", "modulePaths": [ "<rootDir>/app/static/react/" ], "moduleDirectories": [ "node_modules" ...

Having trouble with JavaScript's Date.getUTCMilliSeconds() function?

I have a straightforward question for you. Take a look at this Angular App and try to create a new date, then print the number of UTC milliseconds of that date in the console. Can you figure out why it is returning zero? ...

Tips for inserting a php variable into an html document

I am trying to figure out how to export a variable from a php file into an html file. The php file I'm working with is example.php and it contains the following code: <?php $array= ['one','two']; ?> The html file is named ...

Can we avoid the error callback of an AJAX request from being triggered once we have aborted the request?

Initially, I encountered a challenge where I needed to find a way to halt an AJAX request automatically if the user decided to navigate away from the page during the request. After some research, I came across this helpful solution on Stack Overflow which ...

Unable to revert input to its previous state after setting the value attribute in ReactJS

It may seem strange, but I set the value attribute of the input tag to a random state. However, I am unable to type anything into the input field. The input field is meant to be cleared after clicking, but unfortunately, nothing happens. (I apologize if ...

What is the best way to show the probability of users' bets in percentage form based on their wagered amounts?

I am currently working on creating a Jackpot Roulette game that features a main pot. Each round sees users joining and placing bets that contribute to the main pot, with the winner taking home the entire amount. My goal is to provide each user with real-t ...

Ways to automatically refresh HTML table in Django framework

How can I dynamically update the search content under the hostname column in an HTML table? The search content needs to be updated every time, and the row number should increase according to the number of hostnames entered by the user. Below is my index.h ...

React-Redux - sending an action to update multiple components

I am facing a dilemma where I'm not sure if my issue stems from missing the bigger picture or if it's a valid concern in redux... There is an SVG chart on my page with a fixed size. Sometimes, when the user opens a panel, the width of the chart ...

Issues with Braintree webhooks and CSRF protection causing malfunction

I have successfully set up recurring payments with Braintree and everything is functioning properly. Below is an example of my code: app.post("/create_customer", function (req, res) { var customerRequest = { firstName: req.body.first_name, lastN ...

Angular 2 decorators grant access to private class members

Take a look at this piece of code: export class Character { constructor(private id: number, private name: string) {} } @Component({ selector: 'my-app', template: '<h1>{{title}}</h1><h2>{{character.name}} detai ...

`How can I customize the appearance of individual selected <v-list-item> across various sub-groups?`

As a newcomer to Vuetify and Vue in general, I am struggling to solve a specific issue. I need to create multiple sub-groups where only one option can be selected within each "parent" list. Consider an array of cats: options:["Crookshanks", "Garfield", " ...

Error occurred due to a response timeout when attempting to retrieve http://registry.npmjs.org/@typescript-eslint%2feslint-plugin after 30 seconds

The current NPM version I am using is 6.14.4. While attempting to create a react application with 'npx create-react-app helloapp', an error occurred indicating that the data could not be fetched. The specific error message received was: npm ERR ...

What could potentially be the reason behind the incapability of the next.js Image component to transform the svg into a

Unique Context I recently developed a minimalist Hero + Navbar using Next.js. The site utilizes the powerful next.js Image component to display images. Surprisingly, all three images on the website, which are in .webp format, load instantly with a size of ...

Looking to integrate WhatsApp into your next.js website for optimal responsiveness?

I am trying to incorporate WhatsApp into my next.js responsive website. I have already added an icon which successfully opens the WhatsApp web version when clicked in desktop view. However, I want to make sure that when a user accesses the website on mobi ...

Is there a way to add a <video> tag in tinymce editor without it being switched to an <img /> tag?

I am attempting to include a <video> tag within the tinymce editor, but it keeps changing it to an <img> tag. Is there a way to prevent this conversion and keep the <video> tag intact? I want to enable videos to play inside tinymce whil ...

Managing additional components in request JSON when communicating with DialogFlow, previously known as Api.ai

My current challenge involves enhancing the information sent in a JSON request from my application to DialogFlow. While I am familiar with triggering events to send data calling an intent through the method described in Sending Parameters in a Query Reques ...

What is the best way to transfer the content from a tinyMCE textarea editor to an inner controller using Symfony3 and Ajax

I have two small rich text editors identified as #homepage and #thankyoupage. My goal is to submit the content of these TinyMCE text areas to a Symfony controller. Below is my front-end implementation: https://i.stack.imgur.com/TE1Ys.jpg Currently, I am ...

Leveraging JavaScript within the Selenium JavaScript Executor

I am trying to check if the required text is visible on the page, but I am unable to use the gettext() method from Selenium WebDriver due to a permission exception. As a workaround, I have created a JavaScript script to compare the text. String scriptToE ...