ByteNoteByteNote

字节笔记本

2026年8月29日

react-scan:看清 React 重渲染

API中转
¥120

React 一卡顿,很多人第一反应是开 React DevTools Profiler。能用,但噪音大:必要渲染和不必要渲染混在一起,你得自己猜哪个组件值得改。react-scan 换了个思路:丢进页面就能高亮「该优化」的组件,几乎不用改业务代码。

它解决什么问题

React 用引用比较 props。父组件随便传一个内联函数或对象,子组件就会跟着重渲染,哪怕看起来「数据没变」。小项目无所谓,列表一长、表单一复杂,帧率就掉下来。

常见工具各有短板:

  • React DevTools:信息全,但不直接告诉你哪些渲染是多余的
  • why-did-you-render:要改组件源码才能挂上
  • Profiler API:适合写进自己的监控,上手成本高

react-scan 的目标很简单:零侵入、视觉反馈、开发时就能用。

项目地址:aidenybai/react-scan,站点:react-scan.com

最快上手

本地项目根目录跑一次:

bash
npx -y react-scan@latest init

它会探测框架(Next、Vite 等)、装依赖,并写好入口配置。不想自动改文件的话,也可以手动装:

bash
npm install -D react-scan

用 script 标签(Vite / 普通 SPA)

index.html 里,把脚本放在其他脚本之前

html
<script
  crossorigin="anonymous"
  src="//unpkg.com/react-scan/dist/auto.global.js">
</script>

Next.js App Router

app/layout.tsx<head> 里用 beforeInteractive

tsx
import Script from "next/script";

export default function RootLayout({ children }) {
  return (
    <html>
      <head>
        <Script
          src="//unpkg.com/react-scan/dist/auto.global.js"
          crossOrigin="anonymous"
          strategy="beforeInteractive"
        />
      </head>
      <body>{children}</body>
    </html>
  );
}

模块方式(要更细的控制)

入口文件里,必须先于 React / ReactDOM 引入:

tsx
import { scan } from "react-scan";
import React from "react";
import ReactDOM from "react-dom/client";

scan({
  enabled: true,
  log: false,
  showToolbar: true,
});

顺序错了就钩不上 DevTools 通道,页面上什么都看不到。

CLI 扫任意页面

本地起好应用后,也可以不改仓库,直接扫:

bash
npx react-scan@latest http://localhost:3000

甚至能扫公开站点做对比,适合快速验证「是不是自己这套写法有问题」。

页面上你会看到什么

启用后右下角一般有工具条。交互时组件外框会闪高亮:渲染越频繁、越可疑,提示越明显。对照操作路径(点输入框、切 Tab、滚列表),一眼能定位「谁在跟着抖」。

常用选项:

选项作用
enabled开关,默认开
log把渲染打到控制台
showToolbar是否显示工具条
animationSpeedslow / fast / off
dangerouslyForceRunInProduction强制在生产跑(一般别开)

还有 useScansetOptionsonRender(Component, cb),适合只盯某一个昂贵组件。

怎么读结果、怎么改

看到某个叶子组件狂闪时,先问三件事:

  1. props 是不是每次新建? 内联箭头函数、内联 style 对象、每次 filter 出来的新数组都会制造新引用。
  2. 状态是不是放太高? 无关字段的更新会拖整棵子树一起渲染。
  3. 列表有没有稳定 key? key 乱跳会导致整行重建,看起来像「疯狂重渲染」。

常见改法:用 useCallback 稳住事件回调,用 useMemo 或把常量提出组件外稳住对象;真的需要隔离时再用 React.memo,别一上来全包一层。

和 React Doctor 的关系

官方 README 现在会提示:日常仍可用 React Scan,但更推荐面向编码代理的 React Doctor(静态检查架构、安全、无障碍等)。如果你还在本地肉眼抠渲染,react-scan 依然够用;团队已经把性能检查交给 Agent 流水线,可以一起看 Doctor。

小结

react-scan 把「猜谁在重渲染」变成「看谁在闪」。开发环境加一行 script 或跑 npx react-scan init,配合工具条就能排大部分无意义更新。装的时候记住:脚本要在 React 之前;生产默认别开。GitHub 上大约两万星,MIT 协议,适合放进前端性能排查清单。

分享: