React调试利器:React DevTools
得益于 chrome 浏览器强大的调试能力, console.log 可谓是前端开发中解决未知问题最直接的办法,遇事不决,打个日志,简单粗暴🏈。但是在 React 项目中其实有更好的调试方案,那就是官方(脸书)出的 react devtools ,可以针对性的做一些代码的调试。想尝试react devtools的掘友,不妨先看下这篇文章,了解下此工具能做些什么。(小长文警告,可先Mark一下👍)
安装&打开 ⚒
安装
在web端的 react 项目里, React DevTools 是作为浏览器的插件引入进来, chrome 中可以在扩展程序里面添加(懂的掘友已经打开了商店🐶), firefox 添加链路:打开菜单-->Web开发者-->获取更多工具-->搜索"React Developer Tools"-->安装
chrome:
firefox:

打开chrome网上商店可能需要科学上网,firefox不需要科学上网也可正常安装插件,使用上无差别
工具入口
如果检测到当前web是 react 项目,右上角的工具小图标(地址栏右侧)会发生改变,分别对应着:
debug版本 的 react 项目,正在coding👨🏻💻
生产版本的react,说明已经打包发布了
表示当前依赖的react版本比较老,一般会在react15以及更早的版本出现
Web中并没有检测到有react的依赖 ❌
chrome 中右键点击检查,打开调试器,然后发现在调试器的tab栏末尾有最后两栏比较特殊的tab,分别是⚛️ Components和⚛️ Profiler,这两个就是 react devtools 的功能入口了,下面会来介绍各自的功能。

JSX结构树 🌲
为了方便演示功能,这边做了一个常见的表格展示和搜索功能,组件层级是 User 组件下面有两个 UserSearch 和 UserList 组件。

定位
JSX 是 React 语法中的重点, Components 工具也是有很大一部分展示的是 react 的 JSX 虚拟 Dom 树,左上角的拾取图标用起来和 chrome devtools 里的拾取是一样的,点击以后就能定位到具体想要查看详情的组件。

定位到了 UserSearch 组件
在项目中用了一些 React-router , redux 等工具后,虚拟 Dom 树可能会受到一些侵入,比如 Dom 树中多了一些 Conext.Consumer 的结构,这些是 context 的语法,不管这些结构,双击目标组件即可下钻定位到这个组件的详细结构中,比如:双击 User 组件:
这样是不是清晰很多, User 下有个 Suspense , Suspense 下有两个自定义的组件,红色下划线标注的是该组件在全局 Dom 树里的各个层级。
Suspense是配合react懒加载使用的,文档:zh-hans.reactjs.org/docs/code-s…

过滤器
还有个小技巧可以轻松过滤掉一些不想要展示 Dom ,点开 setting 小图标的下拉框里,有一栏是组件的设置,然后找到"Hide components where",在这里可以添加过滤器,从而进行过滤的设置,下面列出了各个配置代表什么含义。
过滤器第一栏key:
| 名称 | 含义 |
|---|---|
| location | router路由匹配的组件 |
| name | 组价名 |
| type | 各种组件类型细分(参考下面表格) |
| hoc | 高阶组件 |
location和name都是进行正则匹配的

type可选值:
| 名称 | 含义 |
|---|---|
| class | 继承React.Component的类组件 |
| context | 共享上下文context |
| function | 函数式组件 |
| forward ref | 函数式组件传递ref的HOC |
| host(e.g ) | 浏览器支持的html元素,div,h1,p |
| memo | 函数式组件做props优化的HOC |
| other | 其他❓(待补充) |
| profiler | 测量性能的 |
| suspense | 懒加载根组件 |
单组件调试 🔧
定位到目标组件后就可以进行单组件调试,双击组件, react devtools 的右侧就会出现组件相关信息,比如 props , state , hooks , render by 等。
从 props 的信息就可以看出, User 组件是 Router 下的第一层级组件,会有 location , history , match 等额外信息。
class 类组件会更好,hooks 的根state 会缺少属性名,暂时可以通过useState<object>({msg: 'hello'}) 的方式绕过,希望后续迭代会解决这个问题
光能看属性不行,要中看又中用才行,细心的掘友已经在右上角发现一排的 icon 了:
1. 显示懒加载的fallback状态
这个时间样式的按钮是和懒加载 Suspense 相关的,当 Suspense 组件的 children 还没加载出来的时候,有一个过渡的 loading 效果,点击按钮,就会显示 fallback 属性里的 ReactNode ,用来预览加载效果还是不错的。
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</div>
);
}

这边引入了 antd 的 Skeleton 效果作为 loading 的中间态,小图标高亮就说明处于 loading 状态调试。
2. 检查组件的真实Dom
在 React 中写的 JSX 代码渲染出来的组件树其实都不是真实的 DOM 树,所以有调试样式、修改文案、直接操作 DOM 的需求,还是需要切回 chrome devtools 的 Element ,然后定位 Element 又是一顿拾取操作就会稍显不便,这个小眼睛图标的按钮就是用来定位组件真实Dom的。
这里通过 UserSearch 组件定位到了真实的 dom 树,对于一些层级比较深的 dom 结构,或者 z-index 层级复杂的dom来说,这个功能定位还是相当方便的。
3. debug信息
这个小虫的按钮在最开始用的时候会挺懵逼的,点了以后好像没有什么作用,然后悬停一会会有一段文字:
log this component data to the console(将组件数据记录在console中)
然后切换到 chrome devtools 的 console 就能发现端倪了,这里出现了和 UserSearch 相关的组件信息:
根据提示信息,右键任何值,然后点击"Store as global variable"保存为全局变量,我们这里选择了 Props 下的 onSearch 方法:
console 中会出现新的一个 temp1 变量,这个变量就是指向 onSearch 的引用值,调用 temp1 函数等同于 onSearch , onSearch 的业务逻辑是根据参数过滤用户列表,下面就是过滤出包含"xu"的记录:
这种 debug 方式在一些特殊场景下比较方便,比如通过普通的页面交互无法触发,需要异步接口返回值才能触发等等。
4. 定位Source-map信息
最后一个按钮很熟悉,平时都会在一些组件库文档中的代码案例中看到,比如 antd , fusion , iview 等UI组件库,用来作为展开代码的调试入口, react devtools 的功能也是类似,这里是定位该组件对应的 Source 文件,这里我就切换到了 UserSearch 对应的 index.tsx 文件中,在开发环境中配置好 source-map ,定位组件就能直接显示源码。
这里的 source 功能就非常强大了,最常用的就是打断点,比如,我们在 resetTrigger 里面打两个断点,点击重置按钮后就会触发断点:

并且观察右侧栏的 Scope 中会有闭包信息,这里的闭包其实就是 useState API 保存函数式组件所产生的, filter 就是输入框里的内容,这种调试就可以避免了因为 console.log 修改代码后还要重新编译项目,还有可能会留下一些脏代码。
性能问题追踪 🚥
还有一个⚛️ profiler是什么东西呢,可能刚开始接触 React 的同学可能不太了解,在 react 的官方文档中有介绍一个Profiler API ,能添加在 React 树中的任何地方来测量树中这部分渲染所带来的开销,用法:
render(
<App>
<Profiler id="Navigation" onRender={callback}>
<Navigation {...props} />
</Profiler>
<Main {...props} />
</App>
);
onRender 中的回调函数 callback 中的入参包含了子组件内所有的渲染信息,有利于排查组件的性能问题:
function onRenderCallback(
id, // 发生提交的 Profiler 树的 “id”
phase, // "mount" (如果组件树刚加载) 或者 "update" (如果它重渲染了)之一
actualDuration, // 本次更新 committed 花费的渲染时间
baseDuration, // 估计不使用 memoization 的情况下渲染整颗子树需要的时间
startTime, // 本次更新中 React 开始渲染的时间
commitTime, // 本次更新中 React committed 的时间
interactions // 属于本次更新的 interactions 的集合
) {
// 合计或记录渲染时间。。。
}
虽然在项目中调试比较灵活,但是对项目有一定的代码侵入,甚至会有一些性能的损耗,所以当遇到使用全局 profiler 的场景的话,可以优先尝试一下用 React devtools 的 profiler 功能。
下面为了测试 profiler 功能,在 UserList 组件中增加了一万条记录来显示,看下具体的耗时如何:
这里是一个典型的性能分析火焰图,展示的是当前这个页面中,各个组件的耗时情况,如果是有耗时比较长的异常组件,横向柱状图会显示成黄色,甚至更警示🚨的颜色,这里很明显, UserList 的耗时相当长,这很符合我们的预期。
在 profiler 的系统设置中,还能打开组件何时渲染的开关,以及隐藏固定渲染时间以下的组件:

这里"Why did this render"就说明了 Route 组件是第一次渲染,渲染了12.8毫秒
结束 ⌛️
这边介绍了一些常用的 react 调试方法,还没有涵盖到 React Devtools 所有的功能,官方也提供了各自功能对应的英文教程,下面的传送门👇就是具体教程链接,感兴趣的掘友可以进去看看。
PS: 文中有任何错误,欢迎掘友指正
往期精彩📌
转载自:https://juejin.cn/post/6877546408925200391