Skip to content
New issue

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

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

Already on GitHub? Sign in 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)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in 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