React 批判 2 则

React 哲学号称一套一套的,我也总结过一部分。React 的某些设计确实是挺巧妙的,但这只是 React 的其中一面。

某些情况下,这些说辞真的是一种对 React 的"自适应",换言之,找理由来掩饰 React 的设计缺陷。在某些场景下,这些设计缺陷会变得很难绕过,甚至绕不过,要不怎么说用 React 心智负担高呢。

事件的依赖

useEffect 依赖管理十分困难这件事众所周知,这个问题也算是其中一个特别难解决的分支。

举个例子,这里有一个非 React 原生库,想要包装成 React 组件。

viselect/packages/react/src/SelectionArea.tsx at master · simonwep/viselect

可以看到作者在封装的时候是没有把 useEffect 里所有使用的值都加入依赖,直接当初始化使用。当然一般情况下是没有问题的,但是如果你的传入的 props.onStart 里面引用了 useState 的变量呢?

那就完了。它不会生效的,因为该state更新时,这个 useEffect 根本不会更新,所以拿到的永远只有最开始的值。

例子,注意图中高亮区域:

如果把 props.onStart 加入了依赖又会怎么样呢?当然可以的,但是这又意味着整个初始化过程会重复运行,这简直毫无意义,纯纯的嫌用户电脑性能太高。

那到底怎么办?你可以把函数里面用到的会变化的值统统换成 ref,这样能用,不过非常难看,我们接着看。

其实有比较官方、也优雅一点的办法的:使用 useEffectEvent,至少它现在还叫这个名字,因为 React 到 19 发布为止,它都还是个实验性功能。

useEffectEvent 里面的函数不需要写依赖,依然能让所有使用的值是最新的。使用的场景就基本针对于上述的"事件触发"场景。

官网给出的示例代码:

tsx 复制代码
function ChatRoom({ roomId, theme }) {
  const onConnected = useEffectEvent(() => {
    showNotification('Connected!', theme);
  });

  useEffect(() => {
    const connection = createConnection(serverUrl, roomId);
    connection.on('connected', () => {
      onConnected();
    });
    connection.connect();
    return () => connection.disconnect();
  }, [roomId]); // ✅ All dependencies declared
  // ...

清理顺序

useEffect() parent-child cleanup order · Issue #16728 · facebook/react

useEffect 的清理看起来很优雅,所有相关代码都内聚在一个函数里。

然而,React 清理副作用时的顺序有点任性,有可能你在父组件清除函数已经把你要用的东西 destroy 了,子组件的清除函数还使用了被父组件 destroy 的对象,于是产生了很奇妙的错误,这又是一个对非 React 原生库接入非常不友好的一个点。

而且,这个问题 React 团队甚至是不打算解决的。一般情况,你可以冒着内存泄漏的风险不管它,如果你一定要解决的话,你就得自己写 workaround 来处理全局的 destroy 了。

所以

虽然 React 确实好用,但是在某些情况,例如你使用了非 React 原生的 UI 或事件库,确实不好用(废话文学)。

相关推荐
m0_7190841132 分钟前
React笔记张天禹
前端·笔记·react.js
Ziky学习记录1 小时前
从零到实战:React Router 学习与总结
前端·学习·react.js
wuhen_n1 小时前
JavaScript链表与双向链表实现:理解数组与链表的差异
前端·javascript
wuhen_n1 小时前
JavaScript数据结构深度解析:栈、队列与树的实现与应用
前端·javascript
我是一只puppy1 小时前
使用AI进行代码审查
javascript·人工智能·git·安全·源代码管理
颜酱1 小时前
从二叉树到衍生结构:5种高频树结构原理+解析
javascript·后端·算法
狗哥哥1 小时前
微前端路由设计方案 & 子应用管理保活
前端·架构
青青家的小灰灰1 小时前
React 19 核心特性与版本优化深度解析
react.js
前端大卫2 小时前
Vue3 + Element-Plus 自定义虚拟表格滚动实现方案【附源码】
前端
却尘2 小时前
Next.js 请求最佳实践 - vercel 2026一月发布指南
前端·react.js·next.js