React 19.2 之后 React Compiler 自动完成记忆化,useMemo/useCallback 是否该全删?本文讲清编译器的工作边界、三类仍需手写记忆化的场景,以及老项目渐进接入的可执行步骤。
React 19.2 之后,React Compiler 正式进入稳定可用阶段。它带来了一个足以改变日常编码习惯的能力:自动记忆化(auto-memoization)。于是社区里最常被问的一句话变成了——useMemo、useCallback、React.memo 是不是可以全删了?
答案是:大部分可以删,但有几种情况必须保留。本文讲清编译器的工作边界、三类仍然需要手写记忆化的场景,以及老项目渐进接入的可执行方案。
一、版本坐标
截至 2026 年 9 月,react 与 react-dom 的最新版本为 19.2.8。React Compiler 自 19.2 起可以作为稳定能力使用,配套的代码检查由 eslint-plugin-react-hooks 提供。版本信息可随时在 npm 上的 react 包页面核对。
二、React Compiler 到底做了什么
一句话概括:编译器在构建期分析组件的数据流,自动插入等价的记忆化代码,让组件在 props 或状态没有本质变化时跳过重渲染。
它分析的核心问题是——哪些值的变化会真正影响输出。对于纯计算、字面量、以及依赖链清晰的值,编译器能安全地推导出缓存边界;对于它无法证明安全的情况,会选择 bail out(放弃优化),退回普通重渲染,而不是给出错误结果。

理解这一点很重要:编译器优先保证正确性,其次才是性能。所以”开了编译器就一定更快”是误解,它只是把手写记忆化里大量机械、易错的部分自动化了。
三、三种写法的对比
以”过滤一个大列表”为例。
1. 完全手写(编译器时代之前)
function List({ items, keyword }) {
const filtered = useMemo(
() => items.filter(i => i.name.includes(keyword)),
[items, keyword]
)
const onSelect = useCallback((id) => { /* ... */ }, [])
return <Table data={filtered} onSelect={onSelect} />
}
export default React.memo(List)
问题在于依赖数组靠人维护:漏写会拿到过期值,多写会让缓存失效,而 onSelect 这类回调经常因为”忘了包一层”导致子组件天天重渲染。
2. 编译器接管后
function List({ items, keyword }) {
const filtered = items.filter(i => i.name.includes(keyword))
const onSelect = (id) => { /* ... */ }
return <Table data={filtered} onSelect={onSelect} />
}
代码回到最自然的样子,缓存由编译器插入。可读性和正确性的收益立竿见影——尤其是新人不理解依赖数组语义时造成的隐性 bug。
3. 仍然需要手写的场景
下面三类,编译器帮不上忙或者不该帮:
- 依赖了编译器看不到的外部值:例如
ref.current、模块级可变单例、DOM 直接读取。编译器无法追踪这些值的变化,缓存可能导致读到脏数据; - 需要稳定引用语义的对外契约:把函数作为长期订阅的回调传给第三方库(事件总线、WebSocket、原生监听器),这些库内部可能按引用做增删,引用变化会引发反复解绑重绑;
- 计算极其昂贵且命中率高:例如数万行数据的聚合、复杂图表布局计算。编译器按数据流分析,未必能识别出”这个值值得跨多次渲染缓存”的业务语义,此时显式
useMemo依然是明确且可控的表达。
四、工程落地:老项目怎么接
- 先上 lint,再上编译。 把
eslint-plugin-react-hooks的编译器规则跑起来,它会告诉你哪些组件被 bail out 以及原因,这是最直接的体检报告; - 按目录渐进开启。 优先在交互密集、重渲染明显的模块(表格、编辑器、看板)开启,别一次性全量;
- 清理要有顺序。 先删
React.memo和纯机械包装的useCallback,再评估useMemo;删完用 React DevTools Profiler 对比关键路径的重渲染次数; - 把性能写进测试。 对核心页面做一次交互耗时的基线采集,接 CI 回归,避免”优化”变成回归。
判断标准不是”代码里还有没有 useMemo”,而是一次交互里发生了多少次不必要的重渲染。用 Profiler 的数字说话,比争论风格有意义。
五、小结
React Compiler 把”记忆化”从开发者手动维护的纪律,变成了编译器保证的默认行为。这不是让 useMemo 消失,而是让它回归本职:只在编译器无法推断、或业务语义需要显式表达时使用。
对新项目,建议从一开始就按编译器的心智模型写组件——保持数据流清晰、避免在渲染中读取可变外部状态。对老项目,按模块渐进接入,用 Profiler 数字验证收益,别为了”看起来现代”做全量重构。
延伸阅读:React 官方文档 · React Compiler、useMemo API 参考、useCallback API 参考。版本信息采集于 2026 年 9 月 1 日。
#React#前端性能优化#编译器#前端工程化

