Display menu on hover reactjs

16,198

Basically each dropdown menu needs to be in its own Dropdown composite component, with its own state and handlers. I forked and updated your demo that hopefully gives you the right idea.

<div>
    <Dropdown
      className="d-inline-block"
      onMouseOver={this.onMouseEnter}
      onMouseLeave={this.onMouseLeave}
      isOpen={this.state.dropdownOpen1}
      toggle={this.toggle1}
    >
      <DropdownToggle caret>Dropdown1</DropdownToggle>
      <DropdownMenu>
        <DropdownItem header>Submenu 1</DropdownItem>
        <DropdownItem>Submenu 1.1</DropdownItem>
      </DropdownMenu>
      &nbsp;&nbsp;&nbsp;
    </Dropdown>
    <Dropdown
      className="d-inline-block"
      // onMouseOver={this.onMouseEnter}
      // onMouseLeave={this.onMouseLeave}
      isOpen={this.state.dropdownOpen2}
      toggle={this.toggle2}
    >

      <DropdownToggle caret>Dropdown2</DropdownToggle>
      <DropdownMenu>
        <DropdownItem header>Submenu 2</DropdownItem>
        <DropdownItem>Submenu 2.1</DropdownItem>
        <DropdownItem>Submenu 2.2</DropdownItem>
      </DropdownMenu>
      &nbsp;&nbsp;&nbsp;
      <br /><br />

    </Dropdown>
    <Dropdown
      className="d-inline-block"
      // onMouseOver={this.onMouseEnter}
      // onMouseLeave={this.onMouseLeave}
      isOpen={this.state.dropdownOpen3}
      toggle={this.toggle3}
    >

      <DropdownToggle caret>Dropdown3</DropdownToggle>
      <DropdownMenu>
        <DropdownItem header>Submenu 3</DropdownItem>
        <DropdownItem>Submenu 3.1</DropdownItem>
        <DropdownItem>Submenu 3.2</DropdownItem>
        <DropdownItem>Submenu 3.3</DropdownItem>
      </DropdownMenu>
    </Dropdown>
  </div>

https://stackblitz.com/edit/reactstrap-v6-2dnzex?file=Example.js

Share:
16,198
Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin almost 2 years

    In a react application, I am using reactstrap css framework to make the dropdowns to list the dropdown menus.

    Example.Js

          <Dropdown
            className="d-inline-block"
            onMouseOver={this.onMouseEnter}
            onMouseLeave={this.onMouseLeave}
            isOpen={this.state.dropdownOpen}
            toggle={this.toggle}
          >
            <DropdownToggle caret>Dropdown1</DropdownToggle>
            <DropdownMenu>
              <DropdownItem header>Submenu 1</DropdownItem>
              <DropdownItem>Submenu 1.1</DropdownItem>
            </DropdownMenu>
            &nbsp;&nbsp;&nbsp;
            <DropdownToggle caret>Dropdown2</DropdownToggle>
            <DropdownMenu>
              <DropdownItem header>Submenu 2</DropdownItem>
              <DropdownItem>Submenu 2.1</DropdownItem>
              <DropdownItem>Submenu 2.2</DropdownItem>
            </DropdownMenu>
            &nbsp;&nbsp;&nbsp;
            <br /><br />
            <DropdownToggle caret>Dropdown3</DropdownToggle>
            <DropdownMenu>
              <DropdownItem header>Submenu 3</DropdownItem>
              <DropdownItem>Submenu 3.1</DropdownItem>
              <DropdownItem>Submenu 3.2</DropdownItem>
              <DropdownItem>Submenu 3.3</DropdownItem>
            </DropdownMenu>
          </Dropdown>
    

    Here I have made the setState to set the state for dropDownOpen in the events such as onMouseOver and onMouseLeave.

    The issue is on hover of single dropdown menu, every dropdown gets opened.

    Click here for Working Demo

    Kindly help me to make the hover dropdown to only list the menus of hovered one and not all at a time.

    Note: In my real application, these dropdown menus will be dynamic, So I cant make any hardcoded state like, dropDown1, dropDown2, dropDown3 ... etc ..

    It may have any n number of dropdowns.. So please give me solution in keeping the dynamic menus into consideration.

  • Admin
    Admin over 4 years
    Whether there is no optimum way of doing it? Here in your example you have repeated the toggle 3 times to make this work but is there no way to make it in a single state? I am strictly following DRY(Don't Repeat Yourself) method, So in review this code will be ignored..
  • Admin
    Admin over 4 years
    And also every menu should be displayed on hover.. Why you have modified 2 and 3rd dropdown it to on click? Everything should be on hover and handled separately..
  • Drew Reese
    Drew Reese over 4 years
    You could try making your own wrapped version of Dropdown that internalizes the state and handlers then compose your menus. This was a quick and dirty to show how to split out the menu items so they weren't locked/driven by a single variable.
  • Admin
    Admin over 4 years
    What would be the solution here if the dropdown menus comes in n numbers as dynamic one??
  • Drew Reese
    Drew Reese over 4 years
    n menus wasn't part of your original question, mate. You could use an array of toggle and hover state values and use the index to access. Simply push new handlers in for each new menu you add.
  • Admin
    Admin over 4 years
    You can provide me right solution by changing the entire approach of mine but keeping things in reactstrap alone.. I am making this in an application where the menus will be dynamic so I cannot give like this dropdown1, dropdown2, dropdown3.. Hope you understand my situation.. Please feel free to post new answer..
  • Drew Reese
    Drew Reese over 4 years
    Hey no worries. Please amend your question and list out requirements and/or restraints on your code, and what your expected result should be. It's much easier to design when you know what the specs are. Try to be as specific and detailed as possible.
  • Admin
    Admin over 4 years
    Yes it is not part of my question but that was my real app scenario.. Even here in dropdown 2 and 3 it was clickable in yours which is not intended.. If we think in user perspective, do you think will it be the right one?
  • warmachine
    warmachine over 4 years
    you can make your DropDown dynamic based on what you are getting from source hit,then use map inside render to make everything dynamic!
  • Amit kumar
    Amit kumar over 4 years
    Hi @TestUser and Drew Reese I have reduces some line using arrow functions: stackblitz.com/edit/reactstrap-dropdown?file=Example.js and if you need this for n dropdown then you can create single drop-down and using props you can create multiple dropdown for this, that is the beauty for react.
  • Admin
    Admin over 4 years
    @DrewReese, Did you get any chance to look into better solution?
  • Drew Reese
    Drew Reese over 4 years
    This solution works well, but has a bug where toggled open menus toggle off when hovered over. You should keep two states for each menu, isOpen and isHovered and set the isOpen prop on the component as the union of them. Something like isOpen={stateKeys[name].isOpen || stateKeys[name].isHovered}. This way one "state" won't override the other.
  • Learner
    Learner over 4 years
    I got little confused @DrewReese, can you fork and update it
  • Admin
    Admin over 4 years
    @DILEEPTHOMAS, Have a look into this link supply.com, this is how my dropdown should be so on hover each one it should display the submenus and user can select from it.. This is how my real app dropdowns will be looking like. Consider only the horizontal dropdowns in this link..