Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

How to get ref to DOM element of Menus/Popovers #14342

Closed
jedwards1211 opened this issue Jan 29, 2019 · 11 comments
Closed

How to get ref to DOM element of Menus/Popovers #14342

jedwards1211 opened this issue Jan 29, 2019 · 11 comments
Labels
component: Popover The React component. new feature New feature or request

Comments

@jedwards1211
Copy link
Contributor

jedwards1211 commented Jan 29, 2019

I'm trying to make material-ui-popup-state's bindHover keep the popover open while either the anchor element or the menu or popover is hovered (jcoreio/material-ui-popup-state#3). I can't do this properly unless I can get a ref to the actual DOM element of the menu or popover.

But with findDOMNode being deprecated, it seems like I'm screwed.

Can't use PaperProps={{ref: c => this.popover = c}}, that gets a reference to a component instead of a DOM element. Paper doesn't support any kind of innerRef prop; I could pass it a component that renders with the ref I need but that would be messy.

To make matters worse, if I find the DOM element with the id I pass to the menu or popover, it's the container element that fills the whole screen rather than the menu/popover part. Same goes for the currentTarget of event handlers passed to menu or popover.

Maybe I can use PaperProps={{ onMouseEnter: e => this.popover = e.currentTarget }}, but the problem with that is the mouseenter event would come after the mouseleave on the anchor element.

This sucks. I kind of hate that the React team doesn't want to allow us to find the root DOM node within a Component.

@eps1lon
Copy link
Member

eps1lon commented Jan 30, 2019

Could you add example code? I think we should work on fixing this with the open prop.

Manipulating the DOM sounds like drilling through the abstraction to control a specific behavior that might cause other parts of the component to fail.

@eps1lon eps1lon added component: Popover The React component. new feature New feature or request labels Jan 30, 2019
@eps1lon
Copy link
Member

eps1lon commented Jan 30, 2019

@jedwards1211 Is this related to #14345? If we resolve #14345 can we close this issue?

@jedwards1211
Copy link
Contributor Author

@epsilon it's related but a solution to #14345 would only solve this issue if it displays the paper of a popover by itself without wrapping it in a modal root.

@jedwards1211
Copy link
Contributor Author

jedwards1211 commented Jan 30, 2019

There's no React-only way to determine if the relatedTarget of a mouseleave is a specific React component. SyntheticMouseEvent.relatedTarget is a DOM element so I have no choice but to get a component's DOM element for this.

@jedwards1211
Copy link
Contributor Author

jedwards1211 commented Jan 30, 2019

And I'm absolutely not talking about manipulating the DOM, I'm talking about the read-only operation of determining whether relatedTarget is a descendant of either the menu or the menu trigger.

@eps1lon
Copy link
Member

eps1lon commented Jan 31, 2019

@jedwards1211 I guess #13722 would solve this? It would enable innerRef for the Paper component.

@jedwards1211
Copy link
Contributor Author

Ah yes, that would solve it!

@oliviertassinari
Copy link
Member

oliviertassinari commented Mar 13, 2019

I'm closing for #10825. It should be good now after @eps1lon work:

      <Popover
        ref={ref => {
          console.log('ref', ref);
        }}
        id={id}

Outputs in the console:

Capture d’écran 2019-03-13 à 17 59 44

@rotimi-best
Copy link

Just in case someone got in here looking for a way to scroll to a particular item in the <MenuItem> component, even after you store the ref and you want to access that item (when you open the menu for example, this means you will pass a function to the onOpen prop), you should have a setTimeout (in that function) to make sure the element has been rendered, if not the ref.current will be null (which sucks).

I spent over 2-3 hours on this issue, I was wondering where the refs was going. My thought was MUI wasn't passing the ref.

Anyways I still love material ui and am a dead end fan for live, @oliviertassinari thank you for all your hard work (including the whole mui team of course) ;)

@oliviertassinari
Copy link
Member

@rotimi-best This is likely because of the portal behavior. I have seen this in some of the core components. What you can do is trigger the scroll only once the ref resolves, not on a setTimeout.

@rotimi-best
Copy link

rotimi-best commented Apr 19, 2021

@oliviertassinari oh that's cool, I tried googling it but couldn't find it. How do I know when a ref resolves in a function (like in a useEffect or a prop function)?

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
component: Popover The React component. new feature New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants