downshift: Selection via mouse click does not work when menu is inside a portal

  • downshift version: 1.3.0
  • node version:
  • npm (or yarn) version:

What you did:

Trying to implement simple select component using Downshift. The requirement for my select is that menu is inside a portal. I’m using react-portal npm package that leverages React’s native createPortal() API.

What happened:

After I’ve put menu inside portal, selection via mouse stopped working. Menu is being closed as always, but selection does not happen.

Reproduction repository:

Here’s a sandbox: https://codesandbox.io/s/w7p91ol19k You can try selecting one of menu items. The onChange is not happening, the state is not changed. Try removing Portal element. Without portal everything works as expected.

I believe, there is something to do with mousedown and blur event handlers. I have found that there are native event listeners for mousedown and mouseup events. They are preventing the selection of item due to calling reset prior to that.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 1
  • Comments: 22 (10 by maintainers)

Commits related to this issue

Most upvoted comments

🎉 This issue has been resolved in version 2.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

I still had the issue (v3.2.10). The solution of @circlingthesun solve it:

@rhinoceraptor thanks. My workaround was to use onMouseDown={e => selectItem(item)}. That looks less hacky 😃

Thanks for the report! We could probably add a feature for the upcoming getMenuProps function (see the pull requests) which would apply a ref so we can check that as well as the root ref… Unless someone else has another idea.

lol, I was just working on this and having a really hard time reproducing it. I finally upgraded the original codesandbox to the latest version of downshift and the bug is gone!

However, it’s still possible to reproduce if the user clicks on a non-item that’s rendered within the portal, like here. So I’ll fix that 😃

I’m planning on spending time soon to finish #285 and resolve this among other updates.

If anyone wants that to happen sooner then please feel free to open a PR 😃

@rhinoceraptor thanks. My workaround was to use onMouseDown={e => selectItem(item)}. That looks less hacky 😃

The behavior of the menu pushing all content below it down the page is undesirable in many circumstances.

You can avoid that with a well-placed position: relative on the container and position: absolute on the menu. You shouldn’t need portals for that.

Downshift has been a total joy to work with so far

I’m so glad!

Hey folks! #285 was merged (into the next branch). Anyone want to work on adding a refKey prop to the new getMenuProps method? Make sure you make your branch off the next branch!

+1 for getMenuProps or any solution that would allow use with a Portal. The behavior of the menu pushing all content below it down the page is undesirable in many circumstances. It would be great render the menu in a portal passing in the values from this.button.getBoundingClientRect() so the menu can be positioned absolutely below the button without pushing content down.

Downshift has been a total joy to work with so far @kentcdodds. Terrific work and I’m looking forward to the updates.

I’m at a cabin with my family right now with very limited internet access, but there is a work around. Any time you don’t like what downshift does with state, you can control it yourself (see the readme). There’s an example you can see here: https://github.com/paypal/downshift/blob/master/stories/examples/controlled.js

It’s not an example of the workarounds necessarily, but hopefully that will point you in the right direction. If someone would like to help out by providing an example in codesandbox or something that’d be great!

I have found: https://github.com/paypal/downshift/blob/master/src/downshift.js#L796-L800

Here there is a check for mouseup event target to be inside the root element. Due to mouseup being browser native event and not a react synthetic one, this condition is met. That’s because the menu is outside of Downshift root element.