🤝 1. React Compiler 如何与 MobX 配合使用?
核心结论:它们是“水火不容”的,配合使用极其困难,甚至是不推荐的。
为什么冲突?
- React Compiler 的假设:它假设 React 的数据流是不可变(Immutable) 的。它通过比较引用的变化来判断是否需要更新。如果引用没变,它就认为数据没变,从而跳过渲染。
- MobX 的机制:MobX 的核心是可变(Mutable) 数据。它通过
observable劫持对象的属性,直接修改store.count = 1。 - 冲突点:当你把 MobX 的 observable 对象传给组件时,对象的引用(内存地址)始终没有变。React Compiler 看到引用没变,就会判定“无需更新”,直接跳过该组件。结果就是:数据变了,但 UI 没变。
如果非要用,怎么办?
如果你必须在项目中同时使用两者,只能采用“隔离”策略:
- 强制“去优化” :
在使用 MobX 的组件上,使用 Compiler 提供的“逃生舱”指令(如'use no memo',具体指令随版本变化),告诉 Compiler 不要优化这个组件。 - 使用
observer包裹:
确保组件依然被mobx-react的observer包裹。observer会强制订阅 MobX 的状态变化。但这会抵消 Compiler 带来的性能红利,相当于在这个组件上退回了 React 18 的模式。 - 最佳实践建议:
在开启 React Compiler 的项目中,强烈建议迁移到 Zustand、Jotai 或 Redux Toolkit 等基于不可变数据或原子化更新的状态管理库,或者直接使用 React 原生的useHook 和 Context。
🐞 2. 如何排查 Compiler 引起的组件不更新问题?
当组件本该更新却没更新时,通常是因为 Compiler 错误地缓存了某些值。排查步骤如下:
第一步:使用官方健康检查工具
在项目根目录运行:
npx react-compiler-healthcheck
- 它会告诉你项目中有多少组件被成功优化,多少被跳过。
- 如果某个组件被标记为“Incompatible”(不兼容),那问题很可能就在这里。
第二步:检查 ESLint 插件
安装 eslint-plugin-react-compiler。它会在代码编辑器中直接标红那些 Compiler 无法安全处理的代码模式(例如在循环中改变函数签名、不规范的副作用等)。
第三步:React DevTools 的“检查为什么没渲染”
- 打开 React DevTools 的 Components 面板。
- 选中那个不更新的组件。
- 查看右侧的 Hooks 或 Props。
- Compiler 优化后的组件通常会看到内部使用了
$开头的缓存变量(如$cache)。 - 关键点:检查 Props 的引用。如果你传了一个在父组件每次渲染都重新创建的对象或函数,但 Compiler 认为它没变,这里就能看出来。
第四步:定位“错误缓存”的代码
通常是以下两种情况:
- 依赖了外部可变变量:组件读取了一个非 React state 的外部变量(如
window.config),Compiler 可能会把它缓存住。 - 闭包陷阱:在
useEffect或事件处理器中,引用了过期的值。
解决方法:在该组件文件顶部添加 'use no memo'(或当前版本的禁用指令),强制关闭该文件的优化,看是否恢复正常。如果恢复了,说明就是 Compiler 误判,需要重构代码或等待 Compiler 修复。
📖 3. Compiler 优化后的代码可读性会变差吗?
这个问题要分源代码和构建产物两个层面来看。
A. 源代码(你写的代码):可读性大幅提升 ✅
这是 Compiler 最大的红利。
- 以前:为了性能,你不得不在代码里到处写
useMemo(() => ..., [deps])、useCallback、React.memo。这些样板代码不仅噪音大,还经常因为漏写依赖数组导致 Bug。 - 现在:你可以删除 90% 的手动优化代码。组件函数就是纯粹的逻辑,
useEffect的依赖数组甚至可以省略(Compiler 会自动推断)。代码变得极其清爽、声明式。
B. 构建产物(浏览器运行的代码):可读性变差,但无所谓 ⚠️
-
变化:Compiler 会将你的组件转换成包含大量
$变量和$cache数组的复杂逻辑。- 原代码:
return <div>{user.name}</div> - 编译后:
const $ = useCache(); if ($ !== user) { ... } return $
- 原代码:
-
影响:如果你在浏览器里直接看打包后的代码(Bundle),确实像“天书”。
-
解决方案:Source Map(源码映射) 。
现代开发工具(VS Code Debugger, Chrome DevTools)非常强大。只要配置好 Source Map,你在断点调试时,看到的依然是你写的原始代码,而不是编译后的乱码。
总结:对开发者来说,代码更好写了;对浏览器来说,代码更复杂了(但更快了);对调试体验来说,只要配置得当,几乎没有影响。