Creating a dynamic state management system for multiple Collapse components can be achieved by utilizing

I am trying to create a Collapse menu from array data,

Currently, when I click on any menu all sub menus expand

I believe my issue lies in not being able to set a unique "open" state for each Main menu

I want to avoid assigning a "state" to accommodate potential future data that may have 3 or 4 levels

I am using React.js and material-ui

Please assist me with this problem

Thank you in advance

const myData = [
  {
    id: '1',
    nameHeader: 'Header1',
    subMenu: [{ id: '1', name: 'subMenu1' }, { id: '2', name: 'subMenu2' }]
  },
  {
    id: '2',
    nameHeader: 'Header2',
    subMenu: [{ id: '1', name: 'subMenu1' }, { id: '2', name: 'subMenu2' }]
  }
]

class Myclass extends Component {
  state = { open: false }

  handleClick = () => {
    this.setState(state => ({ open: !state.open }))
  }

  render() {
    const { open } = this.state
    return (
      <div style={{ marginRight: '15px' }}>
        <List component="nav">
          {myData.map(each => (
            <React.Fragment key={each.id}>
              <ListItem button onClick={this.handleClick}>
                <ListItemText inset primary={each.nameHeader} />
                {open ? <ExpandLess /> : <ExpandMore />}
              </ListItem>
              <Divider />
              <Collapse in={open} timeout="auto" unmountOnExit>
                <List component="div" disablePadding>
                  {each.subMenu.map(subData => (
                    <ListItem key={subData.id} button>
                      <ListItemText inset primary={subData.name} />
                    </ListItem>
                  ))}
                </List>
              </Collapse>
            </React.Fragment>
          ))}
        </List>
      </div>
    )
  }
}
export default Myclass

Answer №1

I am facing an issue where I am unable to set a unique state of "open" for the Main menu.

It seems like you have two different sub menus that you want to collapse/expand independently without affecting each other. To achieve this, you need to implement a way to store the current 'open' state for each menu separately.

You already have unique IDs for your menus, so you can use them to reach your objective. One approach is to enhance your state by including specific settings for each menu:

state = { settings: [{ id: "1", open: false }, { id: "2", open: false }] };

This structure will allow you to track the collapsed status of each menu.

To handle this, you should modify your handleClick function to only update the state of the clicked menu item:

handleClick = id => {
  this.setState(state => ({
    ...state,
    settings: state.settings.map(item =>
      item.id === id ? { ...item, open: !item.open } : item
    )
  }));
};

In your render function, ensure that you pass the correct menu item ID to your handleClick function and select the appropriate open state:

<React.Fragment key={each.id}>
  <ListItem button onClick={() => this.handleClick(each.id)}>
    <ListItemText inset primary={each.nameHeader} />
    settings.find(item => item.id === each.id).open
    ? "expanded"
    : "collapsed"}
  </ListItem>
  <Divider />
  <Collapse
    in={settings.find(item => item.id === each.id).open}
    timeout="auto"
    unmountOnExit
  >
  <List component="div" disablePadding>
    {each.subMenu.map(subData => (
      <ListItem key={subData.id} button>
        <ListItemText inset primary={subData.name} />
      </ListItem>
     ))}
   </List>
 </Collapse>
</React.Fragment>

View the solution in action here: https://codesandbox.io/s/6xjz837j9z

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

JavaScript encounters difficulty in reading the text file

I am working on a project where I need to read a local text file located at /home/myname/Desktop/iot/public/sensordata.txt using JavaScript when a button is clicked on a web page. Below is the code snippet I have been using: <html> <head> ...

What is the strategy to load a div exclusively when triggered by a click event, instead of loading it

Can anyone assist me with a problem I am facing on my scripting page? I am currently working on a website that showcases properties. I would like to know how to prevent a specific div from loading when the page initially loads, and instead have its content ...

Learn the art of generating multiple dynamic functions with return values and executing them concurrently

I am currently working on a project where I need to dynamically create multiple functions and run them in parallel. My starting point is an array that contains several strings, each of which will be used as input for the functions. The number of functions ...

The table fails to refresh after adding, modifying, or removing a row

Incorporating ReactJs with Material-UI, I am working on displaying a table of Car components where the display does not update after any Create, Edit, or Delete action has been performed. Below is the structure: class MainCar extends React.Component { c ...

Displaying a collection of items using Rails, implementing form_for and integrating Ajax functionality

Looking to display a list of "Interests" for users to "follow" by clicking on a button linked to the Interest's image. Once the follow button is clicked, the Interest and its image should be removed from the list. Attempting to use a hide function in ...

Previous states in TypeScript

Just starting out with typescript and trying to work with user files in order to update the state. Currently facing a typescript error that I can't seem to figure out - Error message: Argument of type '(prev: never[]) => any[]' is not as ...

How can I change the "Return" button on the iOS keyboard to a "Next" button using jQuery or JavaScript?

Currently, I am developing an HTML application and working on implementing it for IOS devices such as the IPAD. Within my application, there are multiple text boxes. Whenever a user clicks on a text box to input text, the keypad appears. On this keypad, ...

Is there a way to run a node script from any location in the command line similar to how Angular's "

Currently, I am developing a node module that performs certain functions. I want to create a command similar to Angular's ng command. However, I am facing compatibility issues with Windows and Linux operating systems. Despite my attempts to modify the ...

Tips for including a decimal point in an angular reactive form control when the initial value is 1 or higher

I am trying to input a decimal number with 1 and one zero like 1.0 <input type="number" formControlName="global_velocity_weight" /> this.form = this.fb.group({ global_velocity_weight: new FormControl(1.0, { validators: [Valida ...

How can I use D3.js to form a circular group in an organization structure, link it with a circular image, and connect

Is it possible to create a radial grouped circle using d3.js, similar to the image below: I have written some code as shown below. However, I am facing challenges in connecting every circle with a curved line and displaying a tooltip when hovering over a ...

Unable to access external library using browserify and debowerify

I'm facing a dilemma with my current setup as I'm dealing with a headache. Here's how things are currently configured: Utilizing bower to acquire vendor libraries (specifically angular) Executing gulp tasks to run browserify Implementing d ...

Easily toggle between different content within the same space using Twitter Bootstrap Tabs feature. Display the tabs

I made a modification to the bootstrab.js file by changing 'click' to 'hover': $(function () { $('body').on('hover.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { e.p ...

Does the onwheel event get triggered when scrolling on a trackpad?

Despite being a fundamental inquiry, the answer remains elusive to me. Due to its simplistic nature, there isn't much of an elaborate explanation available. Regrettably, I am lacking access to a laptop for testing purposes. ele.onwheel = function(e) ...

What could be causing the web page to refresh at regular intervals?

As a newcomer to nextjs, I'm puzzled by why my website keeps reloading periodically. I understand that hot code loading is a feature of nextjs and it will reload the page whenever any changes are saved to disk. But how can I determine which specific c ...

Mirror Image Iframes

Currently, I have been tasked with constructing a side-by-side "frame" using HTML. The idea is that when the content in the iframe on the left is selected, it will appear in the iframe next to it on the same page. Here's some additional context: The ...

Tips for running Scrapy and Selenium on a webpage that utilizes angular JavaScript to serve data

I have been working on a web scraper that follows this process: Visit site A -> click on the buy now button -> redirected to Amazon -> scrape data -> return to site A The issue I am facing is that the site is built using AngularJS, and I am having troubl ...

Conceal the element if the offspring is devoid of content

I want to implement a feature where a div is hidden when its child element is empty. To achieve this, I aim to assign the class .no-content to the div if it contains no elements. Below is my existing code with spaces: <div class="ee-posts-list&quo ...

When testing, React does not trigger a rerender when a state change occurs

As part of my testing process, I am currently working on a React component that features a simple switch from Material-ui. This switch is designed to update a boolean field and functions properly when the application is run locally. During the testing pha ...

JavaScript multi-click navigation menu

I'm relatively new to JavaScript and I've been struggling with using multiple onClick attributes. While I have some code that works, I feel like there might be a simpler and cleaner solution to my problem. What I'm trying to achieve is a na ...

Choose2 incorporate on change

I have a Laravel project where I am using the vuexy theme. I've been trying to add an onchange event to my select2 input, but so far I haven't had any success. Here is my select2 input: <div class="col-12 mb-2"> <label class ...