不可变性的神坛与裂缝
React 的核心设计哲学之一是“不可变性”——状态更新必须产生全新的对象,以让 reconciliation 能够通过引用比较快速判断组件是否需要重渲染。这一设计在早期极大地简化了 diff 算法,也让组件树的心智模型变得清晰:UI 是状态的纯函数。然而,当应用规模膨胀到真实企业级时,不可变性开始露出它的獠牙。我们被迫编写大量展开语法(...state),使用 Immer 这样的库来掩盖手动克隆的繁琐,或者在 Redux Toolkit 中配置序列化检查——这些都不是功能需求,而是为了迎合框架的底层假设而付出的认知税。更致命的是,不可变性并没有真正解决“不必要重渲染”问题,仅仅是把它从“检测不到”转移到了“需要手动优化”的领域:useCallback、useMemo、React.memo,每一个都是我们与框架博弈的证据。当团队不得不引入 selector 库或状态拆分策略来避免整棵组件树被一个微小的深层次字段变化拖着刷新时,我们是否曾想过:问题可能根本不在我们的代码,而在 React 对“变化”的定义本身?
信号机制:被遗忘的旧神,还是未来的新王?
如果我们将视线移出 React 的舒适圈,会发现前端生态中早已存在另一种响应范式——信号(Signals)。Solid、Vue 3.0 的 ref/reactive,甚至 Preact 的 @preact/signals,都采用了一种粒度更细的订阅模型:信号本身是可变的,但读取信号的组件会被自动登记为依赖,当信号值变化时,只有真正读取它的副作用(DOM 更新或组件渲染)会被精准触发。这与 React 的“自顶向下重渲染+记忆化”有着本质区别。信号模型本质上是一种推拉结合的反应图:数据变化被“推送”到具体消费者,不再需要全量 diff 或浅比较。对比之下,React 的不可变数据+引用相等更像是一种“蛮力筛查”——我们笃定只要剪枝足够多,就能避开最坏性能。可现实是,每一次状态拆分、每一个 context 的滥用、每一层 memo 的漏写,都会让性能从“可接受”滑向“卡顿”。信号机制在理论上可以销除 React 中 80% 的优化性 hook,因为它从根源上消灭了“过度重渲染”的可能性。为什么 React 迟迟不愿拥抱信号?因为那意味着推翻布局、破坏现状,也意味着与 React 的阵营利益——庞大的 hooks 依赖生态——正面冲突。
React 的兼容性包袱:为什么“重新设计”如此艰难
任何技术决策都不仅是技术问题,更是政治与社会学问题。React 拥有全球最大的前端开发者社区、最丰富的第三方库,以及 Facebook 内部的无数遗留系统。如果 React 19 突然引入一等公民的信号式状态,那么未来的 useTransition、useDeferredValue、Suspense 该如何与之协作?现有的 class 组件是否要双轨制维护?新的并发特性本身就依赖于可中断的渲染,而信号模型的同步传播会破坏时间切片的能力。因此,React 团队选择了第三条路:在现有架构上不断叠加。从早期的 setState 到 Redux,到 Context 再到 Recoil、Zustand,以及现在 React 19 中的 use() 和 Server Components——每一次都是对状态管理的“再次补丁”。但补丁无法解决基础模型的语义鸿沟:React 仍然不知道一个组件实际依赖了哪个状态。它只能假设所有组件都可能依赖所有 state,然后用惰性渲染和记忆化去尽可能挽回。这种“不确定性”就是性能焦虑的根源。我们不禁要问:如果一个框架需要开发者如此小心翼翼地维持性能,它是否还能算作一个“响应式”框架?还是一个需要大量人为纪律的“命令式”渲染器?
第三条道路:细粒度与并发共存的未来图景
我在这里提出一个全新的独立观点:React 其实不需要把 state 的原语从不可变改为可变,而是需要引入“计算依赖的显式声明”——它应该学信号机制,但保留不可变数据作为对外接口。想象一下:在组件内部,我们可以用 useLocalSignal 这样的 hook 来定义细粒度状态,它像信号一样支持精确订阅和局部更新;但对外暴露时,它依然是一个快照式的不可变值,以便配合 Suspense 和并发渲染。更进一步,React 可以自动提取 JSX 中的值读取依赖关系,利用编译器(React Compiler 的高阶形态)在构建时生成依赖图,从而将组件拆分为多个可独立调度的“片段”。这样,我们既获得了信号级的性能精确性,又不需要抛弃不可变性带来的时间旅行和 inspect 能力。这难道是乌托邦吗?不,Solid 的细粒度更新已经证明了它在运行时的高效,而 Svelte 的编译时方法也已经证明了从源码推导依赖是可行的。React 真正缺少的,是打破团队自我设限的勇气。如果 React 不这样做,它将会被 Vapr、Solid 或未来新兴框架从性能至上的关键领域(如数据可视化、实时编辑、大型表格)中边缘化,最终只残留于对生态深度依赖且不在乎性能的 CRUD 应用中。
结语:别让“熟悉的工具”成为思想的牢笼
作为开发者,我们往往习惯用“React 就是这样”来为自己的架构缺陷做辩护。但真正的技术成熟是敢于质疑基石。我的观点很尖锐:React 的不可变状态与全量重渲染模型,在当下是一个“技术债”而非“护城河”。它靠着强大的生态和先发优势持续输血,但每一次我们费力地编写 memo 选择器,实际上都在为这个早已过时的决策买单。或许未来的某一天,我们回头看现在的 React 代码,就像一个使用汇编语言却坚持手写最优跳转表的人一样诚恳而笨拙。与其继续往一座老房子上加装窗户,不如在它旁边建起一座以响应式信号为基石的新结构。到那时,状态管理将不再是前端应用性能的瓶颈,而我们也会彻底告别这个黏腻的“状态困境”。