39

I'd like to be able to figure out what React component is associated with a certain DOM element.

For example, say I have a div, and I'm rendering my entire application using React. The div has to be rendered by a React component - but which one?

I know that React supplies the method "getDOMNode" to get the DOM node associated with a React component, but I'd like to do the opposite.

Is this possible?

Brad Parks
  • 66,836
  • 64
  • 257
  • 336

3 Answers3

17

No.

A central concept in React is that you don't actually have a control in the DOM. Instead, your control is that factory function. What's in the DOM is the current render of the control.

If you actually need this, you can keep an object as a global variable, whose keys are the string representations of the names of factory functions, and whose values are the factory functions, then on your renderable div, keep an attribute containing the name of the factory function.

But chances are this is a question of the XY problem (needing X, seeing a way with Y, then asking how to do Y.) Probably if you'd explain your goal there's a better way that better fits React's top-down conceptual model.

Generally speaking, asking to get access to the control from its render is like asking to get access to an SVG from its cached PNG render. It's possible, but it's usually a red flag that something else is conceptually wrong.

John Haugeland
  • 9,230
  • 3
  • 37
  • 40
  • 3
    Good point, but programs like React Native and tools like React DevTools both create a way to get a React component from the DOM/native element. – frontsidebus Sep 26 '15 at 21:21
  • 1
    There are always exceptions, for example I'm looking into implementing old-school custom DnD instead of using HTML5 DnD so that I can do a lot of snazzy animations and things with the drag feedback image. – Andy Oct 08 '15 at 22:56
  • 1
    No this is not XY problem. I need this for userscript that needs to interact with reactjs webpage. – Tomáš Zato Mar 15 '17 at 12:11
  • @frontsidebus - React Native is required to do so by the way iOS' message-driven UI system works. DevTools does so because it's a debugger. – John Haugeland Mar 15 '17 at 18:29
  • @Andy - you're right, there are always exceptions. I'd put two dollars down that you're easier off with CSS transitions in most cases, though – John Haugeland Mar 15 '17 at 18:29
  • @TomášZato - That is a clear case of the XY problem. To interact with a ReactJS webpage, you should be interacting with the app or dataset above the renderer, as passed down in props. – John Haugeland Mar 15 '17 at 18:30
  • Respectfully, sir, I think you've misunderstood the point of my commentary. Please keep the personal attacks to a minimum. Have a nice day. – John Haugeland Mar 16 '17 at 16:13
11

Here's what I use, with React 15.3.0:

window.FindReact = function(dom) {
    for (var key in dom) {
        if (key.startsWith("__reactInternalInstance$")) {
            var compInternals = dom[key]._currentElement;
            var compWrapper = compInternals._owner;
            var comp = compWrapper._instance;
            return comp;
        }
    }
    return null;
};

And then to use it:

var someElement = document.getElementById("someElement");
FindReact(someElement).setState({test1: test2});
Venryx
  • 15,624
  • 10
  • 70
  • 96
  • For some reason it doesn't work (returns `null`). Though I'm using React 15.3.0 with react-rails — maybe that's the reason. – EugZol Sep 14 '16 at 11:56
  • 1
    This is a hack. Even for a hack it is extremely ugly. It is certainly not something you can rely on. – Aluan Haddad Dec 22 '16 at 14:30
  • 2
    @AluanHaddad Agreed, though it can be helpful for certain debugging tasks during development. – Venryx Dec 23 '16 at 08:49
  • This is about to break with the release of `fiber`. Using undocumented internals with a library that changes as frequently as React is probably unwise – John Haugeland Mar 15 '17 at 18:31
  • 2
    A new version is here that works with Fiber as well: https://stackoverflow.com/a/39165137/2441655 – Venryx Apr 18 '19 at 19:05
7

If your situtation demands getting react element from DOM node, here is an approach, "Communicate via event and call back"

You shall fire a custom event on DOM element and have event listener for that custom event in React component. This will map DOM element back to react component.

selvan
  • 1,298
  • 14
  • 9
  • Awesome suggestion, I have a form validation script that needs to validate a lot of different types of React components. This was AWESOME in combination w/ jQuery `.trigger('custom_event', data)` and listening in `componentDidMount` for that custom_event. – Ross The Boss Apr 01 '16 at 17:15
  • 1
    Very very clever possible solution, a bit troublesome to implement but 5* for the suggestion. – Kayote Apr 28 '16 at 11:28
  • This doesn't get you the child element; it gets you a closure with an outdated copy of the virtual dom node from an old pass of the render, with a dataset that could be out of date, almost is guaranteed to be with flux, and with broken contexts. This is deeply incorrect. – John Haugeland May 27 '16 at 19:17
  • 2
    Can you add an example to your post that describes how you might accomplish this? – Kevin Ghadyani Nov 19 '16 at 01:37