Home > OS >  Close Submenu when opening another with ReactJS
Close Submenu when opening another with ReactJS

Time:04-04

Creating Submenus I find that when opening one of them all the others open and when closing it in the same way they all close.

This is my code:

const DashBoard = () => {

    const [showDropdown, setShowDropdown] = useState(false)

  return (

    <>
        <div>
            <div>
                <div>
                    <img 
                        src={ Logo }
                        alt= "LOGO"
                    />
                    </div>
                    <div>
                        <ul>
                            <li>
                                <div
                                onClick={ () => setShowDropdown(!showDropdown) }
                                >
                                    <FiHome  />
                                    Submenu 1
                                </div>

                                { showDropdown && 
                                
                                    (

                                    <div>
                                    
                                        <ul>
                                            <li>Test</li>
                                            <li >Test</li>
                                        </ul>

                                    </div>
                                    )                        
                                }
                            </li>
                        </ul>
                    </div>

                    <div>
                        <ul>
                            <li className='group'>
                                <div
                                onClick={ () => setShowDropdown(!showDropdown) }
                                >
                                    <FiHome  />
                                    Submenu 2
                                </div>

                                { showDropdown &&                                
                                    (

                                        <div>
                                        
                                            <ul>
                                                <li>Test</li>
                                                <li >Test</li>
                                            </ul>

                                        </div>
                                    )    
                                }
                            </li>
                        </ul>
                    </div>
            </div>
            <div>
                <main>Main Content</main>
            </div>
        </div>
    </>


  )
}

How could I achieve that when opening a submenu the others are closed? I have reviewed that indicating an ID per submenu is possible but I don't know if it is the best way. Thanks.

CodePudding user response:

setShowDropdown(!showDropdown)

This part is making all your dropdowns closed together. And your showDropdown state is only true/false value that cannot help you in identifying which dropdown is open/closed

I'd propose that you should assign menu item name to the state

const [showDropdown, setShowDropdown] = useState() //as default, no menu items are opening

According to your setup, I'd use your sub-menu name for the state value

setShowDropdown("Submenu 1")

onClick logic for opening/closing a sub-menu item

onClick={() => setShowDropdown(showDropdown === "Submenu 2" ? undefined : "Submenu 2")}

Add the condition to check current open/closed sub-menu items

showDropdown === "Submenu 1"

Full implementation can be

const DashBoard = () => {

    const [showDropdown, setShowDropdown] = useState()

  return (

    <>
        <div>
            <div>
                <div>
                    <img 
                        src={ Logo }
                        alt= "LOGO"
                    />
                    </div>
                    <div>
                        <ul>
                            <li>
                                <div
                                onClick={ () => setShowDropdown(showDropdown === "Submenu 1" ? undefined : "Submenu 1") }
                                >
                                    <FiHome  />
                                    Submenu 1
                                </div>

                                { showDropdown === "Submenu 1" && 
                                
                                    (

                                    <div>
                                    
                                        <ul>
                                            <li>Test</li>
                                            <li >Test</li>
                                        </ul>

                                    </div>
                                    )                        
                                }
                            </li>
                        </ul>
                    </div>

                    <div>
                        <ul>
                            <li className='group'>
                                <div
                                onClick={ () => setShowDropdown(showDropdown === "Submenu 2" ? undefined : "Submenu 2") }
                                >
                                    <FiHome  />
                                    Submenu 2
                                </div>

                                { showDropdown === "Submenu 2" &&                                
                                    (

                                        <div>
                                        
                                            <ul>
                                                <li>Test</li>
                                                <li >Test</li>
                                            </ul>

                                        </div>
                                    )    
                                }
                            </li>
                        </ul>
                    </div>
            </div>
            <div>
                <main>Main Content</main>
            </div>
        </div>
    </>


  )
}

CodePudding user response:

It would be good if you make it all dynamic using an array.

Here I have taken an array named menu which includes 3 properties title, visible, and child. And in the HTML, I have used the visible property to show the respective menu's child.

Demo: https://stackblitz.com/edit/react-3w2rns

Solution:

import React, { useState } from 'react';
import './style.css';

export default function App() {
  const [menu, setMenu] = useState([
    {
      title: 'Menu 1',
      visible: false,
      child: [{ title: 'Test 1' }, { title: 'Test 1' }],
    },
    {
      title: 'Menu 2',
      visible: false,
      child: [{ title: 'Test 2' }, { title: 'Test 2' }],
    },
  ]);

  const onMenuClick = (index) => {
    menu[index].visible = !menu[index].visible;
    setMenu([...menu]);
  };

  return (
    <>
      <div>
        <div>
          <div>
            <img src="" alt="LOGO" />
          </div>

          {menu.map((menu, index) => (
            <div>
              <ul>
                <li className="group">
                  <div onClick={() => onMenuClick(index)}>{menu.title}</div>

                  {menu.visible && (
                    <ul>
                      {menu.child.map((item) => (
                        <li>{item.title}</li>
                      ))}
                    </ul>
                  )}
                </li>
              </ul>
            </div>
          ))}
        </div>
        <div>
          <main>Main Content</main>
        </div>
      </div>
    </>
  );
}
  • Related