Downshift: Clicking item via dropdown not working with react-tether

Created on 31 Aug 2017  路  14Comments  路  Source: downshift-js/downshift

  • downshift version: 1.2.0

Relevant code or config:

https://codesandbox.io/s/jlkn76rvlw

What you did:

I'm using react-tether to hoist the dropdown menu (because of overflow issues) outside the parent (moves it to a child of <body>).

What happened:

Using the arrow keys + enter to select an item works great. Clicking a dropdown item does not work though, it simply closes the menu. This same code works if you just remove the <TetherComponent> wrapping. Do I need to somehow use getRootProps? But my understanding was that this is for the wrapper of everything, e.g. including the input. But the issue seems to be with just the wrapper of the menu.

Most helpful comment

I had used @kentcdodds workaround for my mui-downshift component, but while fixing the inability to click on an item, it still had an issue where clicking on the scrollbar and scrolling would close the menu on mouseup.

A better approach, that seems to solve both issues, is to add a onMouseUp handler on your popper/menu and stopping the event from propagating to the window

<Popper onMouseUp={e => e.stopPropagation()}>
  // menu...
</Popper>

@kentcdodds maybe worth adding a getMenuProps with onMouseUp defined?

All 14 comments

I recommend using react-popper. The tether project has seemed to have been abandoned. You can find an example with react-popper here.

Thanks for the speedy reply. react-popper will definitely work but it still doesn't have the portal ability that react-tether provides. I tried implementing react-portal with the react-popper example you linked (wrapping <Portal isOpened={isOpen}> around the <Popper> component but I'm back to the onClick's simply closing the dropdown.

It may have something to do with how react-portal handles outside clicks so I'll do some more digging.

react-popper works just fine with react-portal, make sure to wrap them in the right order (you want react-portal around <Popper /> and not around the whole <Manager /> or inside <Popper />

Yeah I had the portal working with popper, the issue is that when you click a dropdown item nothing happens, see this fiddle

https://codesandbox.io/s/oq0q5jmlqz

when you click a dropdown item nothing happens, see this fiddle

My guess is the fact that the portal is not a child of the downshift root element. In an effort to avoid performance issues of adding a bunch of click handlers on all the items every render, we put a single click handler on the root element of your downshift component:

https://github.com/paypal/downshift/blob/47ee3b82d8aa9233b0f1c904e01ce7cb59fb437d/src/downshift.js#L380-L395

So, if you click on an item outside the root element, then that click handler wont fire. I'm trying to make things work by manually adding a click handler on the item, but that isn't firing for some reason...

Ah, the reason my attempt isn't working is because the menu is closed before the click event fires, so by the time the click event comes around the div item is no longer there to respond to the event.

I'll have to think about this... Unfortunately it wont be as easy as adding an onClick handler for you because that clearly doesn't work. I think what you'll have to do is control the isOpen state and not set it to what downshift says you should set it to if the user clicked in the popover... 馃

This one's a bit tricky.

A definitely hack would be to control the isOpen state and do a setTimeout in your onStateChange handler whenever the isOpen state changes... I'll do that really quick just to make sure it'll work.

So that hack works: https://codesandbox.io/s/z2ywk80z6p

I'm going to leave my investigation at that. I would love an improved solution, but I'm afraid I don't have time to look into it any further. Good luck! Let us know if you come up with something better. I hope we can do something to make it more seamless!

Thanks for taking the time to look at this Kent, I really appreciate all of the work that you do!

I had used @kentcdodds workaround for my mui-downshift component, but while fixing the inability to click on an item, it still had an issue where clicking on the scrollbar and scrolling would close the menu on mouseup.

A better approach, that seems to solve both issues, is to add a onMouseUp handler on your popper/menu and stopping the event from propagating to the window

<Popper onMouseUp={e => e.stopPropagation()}>
  // menu...
</Popper>

@kentcdodds maybe worth adding a getMenuProps with onMouseUp defined?

Thanks for the idea @techniq! I think that would be great to add to our documentation, but I'm not sure that it's necessary for 95% of the use cases so I don't think I want to introduce an onMouseUp prop getter. Thanks again!

The idea was to add a getMenuProps prop getter, but I agree it's unnecessary for most use cases (although hitting the stacking context problem with multiple menu's and using a portal to work around the issue is also probably something worth adding to the docs). I don't think I'll be able to get to a PR soon to update the docs, but if I see no one has when I do get some time, I'll send one your way.

I'll re-open this issue to invite others to add these docs. But they'd be best to be written by someone who's experienced and worked around the issue :+1:

Going to close this for inactivity.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

oliverjam picture oliverjam  路  3Comments

srishanbhattarai picture srishanbhattarai  路  3Comments

kohgpat picture kohgpat  路  3Comments

Vincent-Alibert picture Vincent-Alibert  路  4Comments

the-simian picture the-simian  路  4Comments