React - getting a component from a DOM element for debugging
- LodeRunner28
- 2015-03-28 19:44
- 9
For the purposes of debugging in the console, is there any mechanism available in React to use a DOM element instance to get the backing React component?
This question has been asked previously in the context of using it in production code. However, my focus is on development builds for the purpose of debugging.
I'm familiar with the Chrome debugging extension for React, however this isn't available in all browsers. Combining the DOM explorer and 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 debugging console: getComponentFromElement($0).props
Even in a the React development build is there no mechanism to use maybe the element's ReactId to get at the component?
9 Answers
Here's the helper I use: (updated to work for React <16 and 16+)
function FindReact(dom, traverseUp = 0) { const key = Object.keys(dom).find(key=>key.startsWith("__reactInternalInstance$")); const domFiber = dom[key]; if (domFiber == null) return null; // react <16 if (domFiber._currentElement) { let compFiber = domFiber._currentElement._owner; for (let i = 0; i < traverseUp; i++) { compFiber = compFiber._currentElement._owner; } return compFiber._instance; } // react 16+ const GetCompFiber = fiber=>{ //return fiber._debugOwner; // this also works, but is __DEV__ only let parentFiber = fiber.return; while (typeof parentFiber.type == "string") { parentFiber = parentFiber.return; } return parentFiber; }; let compFiber = GetCompFiber(domFiber); for (let i = 0; i < traverseUp; i++) { compFiber = GetCompFiber(compFiber); } return compFiber.stateNode; }
Usage:
const someElement = document.getElementById("someElement"); const myComp = FindReact(someElement); myComp.setState({test1: test2});
Note: This version is longer than the other answers, because it contains code to traverse-up from the component directly wrapping the dom-node. (without this code, the FindReact function would fail for some common cases, as seen below)
Bypassing proxy components
Let's say the component you want to find (MyComp
) looks like this:
class MyComp extends Component { render() { return ( <ProxyComp> <div id="target">Element actually rendered to dom-tree.</div> </ProxyComp> ); } }
In this case, the FindReact
function will (by default) return the ProxyComp
instance instead, since it's the first component ancestor of the dom-element.
To resolve this, increase the traverseUp
argument until you find the component you wanted:
const target = document.getElementById("target"); const myComp = FindReact(target, 1); // provide traverse-up distance here
For more details on traversing the React component tree, see here.
Function components
Function components don't have "instances" in the same way classes do, so you can't just modify the FindReact
function to return an object with forceUpdate
, setState
, etc. on it for function components.
That said, you can at least obtain the React-fiber node for that path, containing its props, state, and such. To do so, modify the last line of the FindReact
function to just: return compFiber;
debug react js in chrome, Adds React debugging tools to the Chrome Developer Tools. Created from revision 6cceaeb67 on 3/26/2020. React Developer Tools is a Chrome DevTools extension for the open-source React JavaScript Adds React debugging tools to the Chrome Developer Tools. Created from revision 23309eb38 on 5/18/2020.
Venryx
2019-12-12 16:54
Here you go. This 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; };
react get element by id, 1. try componentDidMount, 2. if the input is part of your React component, use refs, e.g. <input ref="name" /> and var name = this.refs.name, 3. Your example input has id="cp-dev1" but you try to get element with id="name" which doesn't exist in the code you have posted. Does it exist anywhere in your app? – pawel Oct 26 '16 at 8:22 getElementById() in React · javascript reactjs getelementbyid. How do I select certain bars in react.js? This is my code:
Guan Gui
2018-01-19 06:20
i wrote this small hack to enable access any react 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
get dom element from react component, EDIT: In react v16.8.0 with functional component, you can define a ref with useRef. Note that when you specify a ref on a functional component, you need to use React.forwardRef on it to forward the ref to the DOM element of use useImperativeHandle to to expose certain functions from within the functional component. Ex: When the ref attribute is used on an HTML element, the ref created in the constructor with React. createRef() receives the underlying DOM element as its current property. When the ref attribute is used on a custom class component, the ref object receives the mounted instance of the component as its current .
Fareed Alnamrouti
2016-05-14 18:03
Here is a small snippet i'm currently using.
It works with React 0.14.7.
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'))
react get dom element, If you worked with React before, you might be familiar with an older API where the ref attribute is a string, like "textInput", and the DOM node is accessed as this.refs.textInput. We advise against it because string refs have some issues, are considered legacy, and are likely to be removed in one of the future releases. Refs and the DOM. Refs provide a way to access DOM nodes or React elements created in the render method. In the typical React dataflow, props are the only way that parent components interact with their children. To modify a child, you re-render it with new props.
Nadav Leshem
2016-03-17 08:16
I've adapted @Venryx's answer with a slightly adapted ES6 version that fit 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; }
react native debugger chrome extension, Created from revision 6cceaeb67 on 3/26/2020. React Developer Tools is a Chrome DevTools extension for the open-source React JavaScript library. It allows you to inspect the React component Note: the React Developer Tools Chrome extension does not work with React You can then select "Debug JS Remotely" from the Developer Menu to start
Noah
2017-06-22 18:35
React 16+ version:
If you want the nearest React component instance that the selected DOM element belongs to, here's how you can find it (modified from @Guan-Gui's 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; };
They trick here is to use the _debugOwner
property, which is a reference to the FiberNode
of the nearest component that the DOM element is part of.
Caveat: Only running in dev mode will the components have the _debugOwner
property. This would not work in production mode.
Bonus
I created this handy snippet that you can run in your console so that you can click on any element and get the React component instance it belongs to.
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; } } });
plugin-react, React AI, used for firing off actions to help the server realtime Fast Leaf Decay, and other physics and entity tweaks to improve the server tick even further! Know when your server spikes and what plugin caused it ingame! Otherwise, install it locally. $ npm install eslint-plugin-react --save-dev. Configuration.
Yangshun Tay
2018-05-07 17:02
Install React devtools and use following, to access react element of corresponding dom node ($0).
for 0.14.8
var findReactNode = (node) =>Object.values(__REACT_DEVTOOLS_GLOBAL_HOOK__.helpers)[0] .getReactElementFromNative(node) ._currentElement; findReactNode($0);
Ofcourse, its a hack only..
react component element id, Assign Id to React components. Ask Question Asked 1 year, This is not working, because id needs to be set on an HTML element, not on some custom component. props will contain the ID from the Dropdown component, but since you're within a React component use this.props . return ( <select
Shishir Arora
2018-06-06 15:02
v15 and v16 compatible with svg, html, comment, 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; } } });
js get react component, To define a React component class, you need to extend React.Component: class Welcome extends React.Component { render() { return <h1>Hello, {this.props.name}</h1>; } } The only method you must define in a React.Component subclass is called render (). All the other methods described on this page are optional. In the typical React dataflow, props are the only way that parent components the raw DOM API // Note: we're accessing "current" to get the DOM node this.
jimmont
2018-12-17 21:05
I've just read through the docs, and afaik none of the externally-exposed APIs will let you directly go in and find a React component by ID. However, you can update your initial
React.render()
call and keep the return value somewhere, e.g.:You can then reference searchRoot, and look through that directly, or traverse it using the
React.addons.TestUtils
. e.g. this will give you all the components:There are several built-in methods for filtering this tree, or you can write your own function to only return components based on some check you write.
More about TestUtils here: https://facebook.github.io/react/docs/test-utils.html
5 things you didn't know about React DevTools, I've just read through the docs, and afaik none of the externally-exposed APIs will let you directly go in and find a React component by ID. However, you can For the purposes of debugging in the console, is there any mechanism available in React to use a DOM element instance to get the backing
Josh from Qaribou
2015-03-28 20:28