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

Lod*_*r28 57 javascript reactjs

出于在控制台中进行调试的目的,React中是否有任何机制可以使用DOM元素实例来获取后备React组件?

之前已在生产代码中使用此问题的上下文中询问过此问题.但是,我的重点是用于调试的开发版本.

我熟悉ReactChrome调试扩展程序,但并非所有浏览器都可以使用.结合DOM资源管理器和控制台,可以很容易地使用"$ 0"快捷方式访问有关突出显示的DOM元素的信息.

我想在调试控制台中编写类似这样的代码:getComponentFromElement($ 0).props

即使在React开发版本中,也没有机制可以使用元素的ReactId来获取组件?

Ven*_*ryx 109

这是我使用的:(更新为React <16和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;
}
Run Code Online (Sandbox Code Playgroud)

然后使用它:

const someElement = document.getElementById("someElement");
const myComp = FindReact(someElement);
myComp.setState({test1: test2});
Run Code Online (Sandbox Code Playgroud)

  • 当修补`render` 不是一个选项(例如通过脚本注入增强页面)时,这是解决方案。 (2认同)
  • (并且您可以执行`FindReact($0)` 来使用*右键单击&gt; Inspect* 来选择元素) (2认同)
  • 它在控制台上对我有用,但是当我尝试从我的 chrome 扩展中使用相同的内容时,“Object.keys”对于同一个 htmlnode 来说是空的。有什么建议么? (2认同)

小智 25

干得好.这支持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;
};
Run Code Online (Sandbox Code Playgroud)


Jos*_*bou 16

我刚刚阅读了文档,并且afaik没有任何外部公开的API会让你直接进入并通过ID找到一个React组件.但是,您可以更新初始React.render()调用并将返回值保留在某处,例如:

window.searchRoot = React.render(React.createElement......
Run Code Online (Sandbox Code Playgroud)

然后,您可以引用searchRoot,直接查看,或使用React.addons.TestUtils.例如,这将为您提供所有组件:

var componentsArray = React.addons.TestUtils.findAllInRenderedTree(window.searchRoot, function() { return true; });
Run Code Online (Sandbox Code Playgroud)

有几种用于过滤此树的内置方法,或者您可以编写自己的函数,仅根据您编写的某些检查返回组件.

有关TestUtils的更多信息,请访问:https://facebook.github.io/react/docs/test-utils.html


Raz*_*med 8

如果有人像我一样努力从 chrome 扩展访问 React 组件/属性,则上述所有解决方案都无法从 chrome 扩展内容脚本中运行。相反,您必须注入脚本标记并从那里运行代码。这是完整的解释: https ://stackoverflow.com/a/9517879/2037323

  • 非常喜欢脱颖而出 (2认同)

Far*_*uti 7

我写了这个小黑客来启用从其dom节点访问任何反应组件

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

然后您可以使用以下方法直接访问任

document.getElementById("lol").react
Run Code Online (Sandbox Code Playgroud)

或使用JQuery

$("#lol").get(0).react
Run Code Online (Sandbox Code Playgroud)