Javascript React-从DOM元素获取组件以进行调试

Javascript React-从DOM元素获取组件以进行调试,javascript,reactjs,Javascript,Reactjs,为了在控制台中进行调试,React中是否有任何机制可用于使用DOM元素实例获取React组件 这个问题以前在生产代码中使用它时被问过。然而,我的重点是为了调试而进行的开发构建 我很熟悉,但这并不是在所有浏览器中都可用。结合DOM资源管理器和控制台,可以轻松使用“$0”快捷方式访问有关突出显示的DOM元素的信息 我想在调试控制台中编写如下代码: getComponentFromElement($0).props 即使在React开发构建中,也没有使用元素的ReactId来获取组件的机制吗?我刚刚阅

为了在控制台中进行调试,React中是否有任何机制可用于使用DOM元素实例获取React组件

这个问题以前在生产代码中使用它时被问过。然而,我的重点是为了调试而进行的开发构建

我很熟悉,但这并不是在所有浏览器中都可用。结合DOM资源管理器和控制台,可以轻松使用“$0”快捷方式访问有关突出显示的DOM元素的信息

我想在调试控制台中编写如下代码: getComponentFromElement($0).props


即使在React开发构建中,也没有使用元素的ReactId来获取组件的机制吗?

我刚刚阅读了文档,并且afaik没有一个外部公开的API允许您直接进入并按ID查找React组件。但是,您可以更新初始的
React.render()
调用并将返回值保留在某个位置,例如:

window.searchRoot = React.render(React.createElement......
然后,您可以引用searchRoot,并直接查看它,或者使用
React.addons.TestUtils
遍历它。e、 g.这将为您提供所有组件:

var componentsArray = React.addons.TestUtils.findAllInRenderedTree(window.searchRoot, function() { return true; });
有几种内置的方法可以过滤此树,或者您可以编写自己的函数,仅根据编写的某些检查返回组件


关于TestUtils的更多信息:

这里是我目前正在使用的一个小片段

它与React 0.14.7一起工作

let searchRoot=ReactDom.render(ROOT,document.getElementById('main');
var getComponent=(comp)=>comp.\u renderedComponent?getComponent(comp.\u renderedComponent):comp;
var getComponentById=(id)=>{
var comp=searchRoot.\u reactInternalInstance;
var path=id.substr(1).split('.').map(a=>'.+a);
如果(comp._rootNodeID!==path.shift())抛出“未知根”;
while(path.length>0){
comp=getComponent(comp)。\u renderedChildren[path.shift()];
}
返回组件实例;
};

window.$r=(node)=>getComponentById(node.getAttribute('data-reactid'))
我编写了这个小技巧,可以从其dom节点访问任何react组件

var ReactDOM = require('react-dom');
(function () {
    var _render = ReactDOM.render;
    ReactDOM.render = function () {
        return arguments[1].react = _render.apply(this, arguments);
    };
})();
然后,您可以使用以下工具直接访问任何组件:

document.getElementById("lol").react
或者使用JQuery

$("#lol").get(0).react

以下是我使用的帮助程序:(已更新以适用于React我已将@Venryx的答案改编为稍微适合我需要的ES6版本。此帮助程序函数返回当前元素,而不是_owner._instance属性

getReactDomComponent(dom) {
  const internalInstance = dom[Object.keys(dom).find(key =>
    key.startsWith('__reactInternalInstance$'))];
  if (!internalInstance) return null;
  return internalInstance._currentElement;
}

给你,这是16号+

window.findReactComponent=函数(el){
用于(el中的常量键){
if(key.startsWith(“\uu reactInternalInstance$”){
常数fiberNode=el[键];
return fiberNode&&fiberNode.return&&fiberNode.return.stateNode;
}
}
返回null;
};
React 16+版本:

如果您想要所选DOM元素所属的最近的React组件实例,下面是如何找到它(从解决方案修改):

这里的技巧是使用
\u debugOwner
属性,它是对DOM元素所属的最近组件的
FiberNode
的引用

警告:只有在开发模式下运行的组件才会具有
\u debugOwner
属性。这在生产模式下不起作用。

奖金 我创建了这个方便的代码段,您可以在控制台中运行它,这样您就可以单击任何元素并获得它所属的React组件实例

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;
    }
  }
});

安装React devtools并使用以下命令访问相应dom节点的React元素($0)

0.14.8

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

当然,这只是一种黑客行为。

如果有人像我一样努力从chrome扩展中访问React组件/属性,那么上述所有解决方案都无法从chrome扩展内容脚本中工作。相反,您必须插入一个脚本标记并从那里运行代码。以下是完整的解释:

编辑的问题可能重复,以解释与之前提出的问题的不同之处。@WiredPairie这实际上有点不同-它更多的是关于树过滤,而不是简单地获取元素。@LodeRunner28检查我的回答是否完美。TestUtils机制正是我想要的。现在在我的调试版本中,我可以提供我可以在控制台中使用一个全局函数,搜索返回的组件列表并将其与所选元素匹配。这是修补
render
时的解决方案,不是一个选项(例如通过脚本注入增强页面)。非常棒的解决方案,对我帮助很大(您可以执行
FindReact($0)
通过右键单击>检查来选择元素)太棒了!完成别人说的是不可能的!它在控制台上对我有效,但当我尝试从我的chrome扩展中使用相同的时,
对象。键对于相同的htmlnode是空的。有什么建议吗?ES6版本很好而且更短。但是,我很好奇,你对“\u currentElement”有什么用对象本身?它没有“setState”这样的常规函数大多数人都希望访问它。@Venryx我们经常使用_currentElement的props属性来进行测试断言。当浅层渲染对特定测试没有用处,但断言props仍然有价值时,这很有用。这是最新的工作解决方案!不过有一个警告-如果
el
不是t的根元素,则不起作用component.to-me stateNode还不够,但它起作用了:
el.\u debugOwner.stateNode.constructor.name
这只返回
{containerInfo:body,pendingChildren:null,implementation:null}
对我来说。另外,constructor.name是
Object
这太棒了,谢谢!例如,假设我使用了这段代码,并且想要设置react组件的道具,使用普通javascript,我将如何得到react来重绘组件?例如,假设我有element.react.props.config.sunhat.enabled=false;那么我该怎么做呢
const target = document.getElementById("target");
const myComp = FindReact(target, 1);   // provide traverse-up distance here
getReactDomComponent(dom) {
  const internalInstance = dom[Object.keys(dom).find(key =>
    key.startsWith('__reactInternalInstance$'))];
  if (!internalInstance) return null;
  return internalInstance._currentElement;
}
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;
};
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;
    }
  }
});
    var findReactNode = (node) =>Object.values(__REACT_DEVTOOLS_GLOBAL_HOOK__.helpers)[0]
.getReactElementFromNative(node)
._currentElement;
       findReactNode($0);