React - getting a component from a DOM element for debugging

For debugging purposes in the console, is there any mechanism available in React to use an instance of a DOM element to get the Backing React component?

This question was asked earlier in the context of using it in production code. However, I focus on developing assemblies for debugging purposes.

I am familiar with the Chrome debugging extension for React , however this is not available in all browsers. By combining the DOM conductor and the console, it is easy to use the "$ 0" shortcut to access information about the highlighted DOM element.

I would like to write code something like this in the debug console: getComponentFromElement ($ 0) .props

Even in the React development assembly, there is no mechanism to use, perhaps a ReactId element to access the component?

+44
javascript reactjs
Mar 28 '15 at 19:44
source share
9 answers

I just read the docs and afaik none of the external APIs will let you directly log in and find the React component by ID. However, you can update your initial React.render() call and save the return value somewhere, for example:

 window.searchRoot = React.render(React.createElement...... 

You can then link to searchRoot and browse it directly or navigate through it with React.addons.TestUtils . for example, this will give you all the components:

 var componentsArray = React.addons.TestUtils.findAllInRenderedTree(window.searchRoot, function() { return true; }); 

There are several built-in filtering methods for this tree, or you can write your own function to return components only based on some kind of validation that you are writing.

Read more about TestUtils here: https://facebook.imtqy.com/react/docs/test-utils.html

+15
Mar 28 '15 at 20:28
source share

Here is what I use: (updated to work with React <16 and 16+)

 window.FindReact = function(dom) { let key = Object.keys(dom).find(key=>key.startsWith("__reactInternalInstance$")); let internalInstance = dom[key]; if (internalInstance == null) return null; if (internalInstance.return) { // react 16+ return internalInstance._debugOwner ? internalInstance._debugOwner.stateNode : internalInstance.return.stateNode; } else { // react <16 return internalInstance._currentElement._owner._instance; } } 

And then use this:

 var someElement = document.getElementById("someElement"); FindReact(someElement).setState({test1: test2}); 
+83
Aug 26 '16 at 11:21
source share

Here you go. It supports React 16+

 window.findReactComponent = function(el) { for (const key in el) { if (key.startsWith('__reactInternalInstance$')) { const fiberNode = el[key]; return fiberNode && fiberNode.return && fiberNode.return.stateNode; } } return null; }; 
+21
Jan 19 '18 at 6:20
source share

I wrote this little hack to allow access to any responsive component from its dom node

 var ReactDOM = require('react-dom'); (function () { var _render = ReactDOM.render; ReactDOM.render = function () { return arguments[1].react = _render.apply(this, arguments); }; })(); 

then you can access any component directly using:

 document.getElementById("lol").react 

or using jquery

 $("#lol").get(0).react 
+5
May 14 '16 at 18:03
source share

Here is a small snippet that I am currently using.

It works with React 0.14.7.

Gist with code

 let searchRoot = ReactDom.render(ROOT, document.getElementById('main')); var getComponent = (comp) => comp._renderedComponent ? getComponent(comp._renderedComponent) : comp; var getComponentById = (id)=> { var comp = searchRoot._reactInternalInstance; var path = id.substr(1).split('.').map(a=> '.' + a); if (comp._rootNodeID !== path.shift()) throw 'Unknown root'; while (path.length > 0) { comp = getComponent(comp)._renderedChildren[path.shift()]; } return comp._instance; }; window.$r = (node)=> getComponentById(node.getAttribute('data-reactid')) 

to start it, open Devtools, highlight the item you want to learn, and enter the console type: $r($0)

+2
Mar 15 '16 at 10:39
source share

Responsive 16+ version:

If you need the closest instance of the React component to which the selected DOM element belongs, here is how you can find it (modified from @ Guan-Gui solution):

 window.getComponentFromElement = function(el) { for (const key in el) { if (key.startsWith('__reactInternalInstance$')) { const fiberNode = el[key]; return fiberNode && fiberNode._debugOwner && fiberNode._debugOwner.stateNode; } } return null; }; 

Their trick is to use the _debugOwner property, which is a reference to the FiberNode nearest component, of which the DOM element is a part.

Warning: components that work only in development mode will have the _debugOwner property. This will not work in production mode.

bonus

I created this convenient snippet that you can run in your console so that you can click on any element and get an instance of the React component to which it belongs.

 document.addEventListener('click', function(event) { const el = event.target; for (const key in el) { if (key.startsWith('__reactInternalInstance$')) { const fiberNode = el[key]; const component = fiberNode && fiberNode._debugOwner; if (component) { console.log(component.type.displayName || component.type.name); window.$r = component.stateNode; } return; } } }); 
+2
May 6 '18 at 21:58
source share

Install React devtools and use the following to access the response element of the corresponding dom node ($ 0).

for 0.14.8

  var findReactNode = (node) =>Object.values(__REACT_DEVTOOLS_GLOBAL_HOOK__.helpers)[0] .getReactElementFromNative(node) ._currentElement; findReactNode($0); 

Of course, this is a hack only ..

+2
Jun 06
source share

I adapted @Venryx's answer with a slightly adapted version of ES6 that fits my needs. This helper function returns the current element instead of the _owner._instance property.

 getReactDomComponent(dom) { const internalInstance = dom[Object.keys(dom).find(key => key.startsWith('__reactInternalInstance$'))]; if (!internalInstance) return null; return internalInstance._currentElement; } 
+1
Jun 22 '17 at 18:35
source share

v15 and v16 compatible with svg, html, comments, text nodes

 /* Node extends text, svg, html usage for node $0: $0.reactive // returns [node, parentNode, rootNode] $0.react.props // {any:'prop'} $0.react.setState(...) // update */ Object.defineProperties(Node.prototype, { _react: {writable:true, value:''} ,reactKey: { get: function(){ let symbol = this._react; if(symbol){ return symbol; } // v15, v16 use a string as key, probably a real symbol in the future symbol = Object.keys(this).find(key => key.startsWith('__reactInternalInstance$')); return Node.prototype._react = symbol || ''; } } // try to find the props/state/React-instance ,react: { get: function(){ let react = this[ this.reactKey ] || null; let $0; if(react){ $0 = react._currentElement; if($0){ // v15 if($0._owner){ return $0._owner._instance; }else{ return $0; }; } $0 = react.return; if($0){ // v16 // develop mode only: return react._debugOwner.stateNode // both develop and prod modes: return $0.stateNode } }else if(this._reactRootContainer){ // v16 _internalRoot === _internalRoot.current.stateNode return this._reactRootContainer._internalRoot; } return react; } } // make a list of self, ancestors that make up this branch of the tree ,reactive: { get: function(list=[]){ let $0 = this; while($0 && !$0[ $0.reactKey ] && !$0._reactRootContainer ){ $0 = $0.previousSibling; }; if($0 && ($0[$0.reactKey] || $0._reactRootContainer)){ list.push($0); }; $0 = this; while($0 = $0.parentNode){ if($0[ $0.reactKey ] || $0._reactRootContainer){ list.push($0); } }; return list; } } }); 
0
Dec 17 '18 at 19:23
source share



All Articles