20

Ok the question is simple. I need to make the dropdown open when mouse hover rather than on click.

Currently my code is as follow.

    <Nav>
      <NavDropdown
        onMouseEnter = {()=> isOpen=true}
        open={isOpen}
        noCaret
        id="language-switcher-container"
      >
        <MenuItem>Only one Item</MenuItem>
      </NavDropdown>
    </Nav>

as you can see, I tried onMouseEnter but no effect. Can someone solve this issue? What attribute should I pass in to achive this.

The API page is here react-bootstrap API page

W.Chen
  • 407
  • 1
  • 4
  • 6
  • first if you need a component to re-render, you need to set a new state, or new props. you can achieve you goal by adding isOpen to state, and then call setState onMouseEnter – Rei Dien Mar 25 '17 at 05:28
  • Yes, I adopted the exact same code as you suggest!! thanks for your help! – W.Chen Mar 25 '17 at 22:15

9 Answers9

20
export class Nav extends React.Component {

  constructor(props) {
    super(props)
    this.state = { isOpen: false }
  }

  handleOpen = () => {
    this.setState({ isOpen: true })
  }

  handleClose = () => {
     this.setState({ isOpen: false })
  }

  render() {
    return (
       <Nav>
        <NavDropdown
          onMouseEnter = { this.handleOpen }
          onMouseLeave = { this.handleClose }
          open={ this.state.isOpen }
          noCaret
          id="language-switcher-container"
        >
          <MenuItem>Only one Item</MenuItem>
        </NavDropdown>
      </Nav>
    )
  }
}

Hope this solves your issue.

Rei Dien
  • 554
  • 2
  • 12
  • 1
    Thanks again, it works. I guess I need to change my mind from traditional frontend to state-controlled rendering technique. – W.Chen Mar 25 '17 at 22:16
  • 8
    The prop `open` does not exist anymore, it has been renamed to `show` – HMR Jan 16 '20 at 08:45
  • This technique will open all dropdown menus on the page. How do you limit this to targeted one, specific, dropdown? Or to hover over multiple other dropdowns throughout the page? – idk Apr 14 '20 at 21:16
  • use the different state for different dropdowns – Adesh Kumar Oct 01 '20 at 10:20
14

A much cleaner pure CSS solution here:

.dropdown:hover .dropdown-menu { display: block; }

Gary Vernon Grubb
  • 9,695
  • 1
  • 24
  • 27
  • 2
    It shouldn't be the accepted answer. Just try to move the mouse over the dropdown-menu element - the dropdown is closed again. – rbtbar Jul 11 '19 at 07:49
  • @rbtbar, are you using nested menus? I have tested without nesting menus and it works fine. "react-bootstrap": "^0.32.4" – Gary Vernon Grubb Jul 16 '19 at 05:20
  • 4
    This doesn't work in newer versions, the dropdown isn't rendered until it's first click. You'd need to trigger the onclick before you could control via css – Schalton Jan 26 '20 at 01:37
3

Having just run into this issue myself, I found out you need both the bootstrap CSS and a parameter for react-bootstrap. Add the following CSS:

.dropdown:hover>.dropdown-menu {
  display: block;
}

Then you need to add the parameter renderMenuOnMount={true} for the child elements to render on load:

<NavDropdown renderMenuOnMount={true}>
  <NavDropdown.Item href="#">Item #1</NavDropdown.Item>
</NavDropdown>
ian ray
  • 131
  • 2
  • 3
1

It's as simple as that :)

<NavDropdown onMouseEnter={(e) => document.getElementById("idofthiselement").click()} onMouseLeave={(e) => document.getElementById("idofthiselement").click()} title="Others" id="idofthiselement">
Siddharth Sogani
  • 321
  • 1
  • 10
1

Inspired by Rei Dien's answer, here's how you could do this using React Hooks.

export const Menu = () => {
  const [menuOpen, toggleMenuOpen] = useState(false);

  return (
    <Dropdown
      onMouseEnter={() => {
        toggleMenuOpen(true);
      }}
      onMouseLeave={() => {
        toggleMenuOpen(false);
      }}
      show={menuOpen}
    >
      <Dropdown.Toggle>
        Menu
      </Dropdown.Toggle>

      <Dropdown.Menu>
        <Dropdown.Item href="#">Menu!!!</Dropdown.Item>
      </Dropdown.Menu>
    </Dropdown>
  );
};
manishie
  • 5,302
  • 1
  • 20
  • 21
0

This seems like a hacky solution, but it was the easiest way to keep my app running after updating.

With the latest update the dropdown-menu isn't rendered until the button is clicked.

I've been using this in my css:

.dropdown:hover .dropdown-menu {
    display: block;
}

and added this to my component

  componentDidMount() {
    // TODO: Fix so menu renders automatically w/out click
    const hiddenNavToggle = document.getElementById('navbar__hamburger_wrapper-hidden_click')
    hiddenNavToggle.click()
    hiddenNavToggle.click()
  }

I added a wrapping div with the given id just to click for this.

I'd love to hear another solution.

Schalton
  • 2,867
  • 2
  • 32
  • 44
0

base on the answer of @Rei Dien

   onMouseEnter = { this.handleOpen.bind(this) }
   onMouseLeave = { this.handleClose.bind(this) }
Ye Cai
  • 25
  • 3
0

Another way

const HoverDropDown = ({ children, ...rest }) => {
   const [show, setShow] = useState(false);

   return (
      <NavDropdown {...rest} show={show} onMouseEnter={() => setShow(true)} onMouseLeave={() => setShow(false)}>
         {children}
      </NavDropdown>
   );
}

<Nav>
   <HoverDropDown id="language-switcher-container" title="Menu">
      <Dropdown.Item>Item 1</Dropdown.Item>
   </HoverDropDown>         
</Nav>
Xavier Lambros
  • 776
  • 11
  • 19
-2

You could replicate this https://codepen.io/bsngr/pen/frDqh which uses the following JS

$('ul.nav li.dropdown').hover(function() {
  $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeIn(500);
}, function() {
  $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeOut(500);
});

Or alternatively you could install a plugin like this https://github.com/CWSpear/bootstrap-hover-dropdown

EDIT: Perfectly fine solutions to bootstrap but I noticed now you said its react and I havent used that before but I dont see why the js above wouldnt work even if it requires tweaking

Dan
  • 951
  • 1
  • 23
  • 46
  • Thanks for your help, yes I'm using bootstrap thus do it this way might not be a good idea, – W.Chen Mar 25 '17 at 00:36
  • Like I say im not familiar with react, but I am with bootstrap. If you pop that code in your own js file and make sure you have a .dropdown-menu etc so that it works, then i dont see why it wouldnt be a good idea? – Dan Mar 25 '17 at 00:44
  • 2
    Using jQuery to manipulate the DOM defeats the whole purpose of using React - a component library. – Foxhoundn Apr 16 '18 at 21:31