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 或事件库,确实不好用(废话文学)。

相关推荐
半个落月7 小时前
LangSmith 全链路观测(下):用 Dataset 与 LLM Judge 量化评估 RA
javascript·langchain
半个落月7 小时前
LangSmith 全链路观测(上):用 LangGraph 与 Milvus 构建可追踪的 RAG 客服
javascript·langchain
Java后端的Ai之路8 小时前
06-React-Props
前端·react.js·前端框架
半个落月8 小时前
LangChain.js Agent 中间件实战:生命周期、动态工具与文件权限
javascript·langchain
Flynt8 小时前
开源"间谍卫星"说数据全是真的,我把它的免key数据源挨个试了一遍
前端·开源·数据可视化
Csvn9 小时前
渲染管线
前端
程序员大阳9 小时前
副队长CSS教程(33)–圆角与透明
前端·css·透明·圆角
志尊宝9 小时前
Vue3 零基础每日笔记(082):文件上传实战——el-upload 校验、自定义上传、头像预览
前端·javascript·vue.js·笔记·#javascript·#vue.js
鬼手点金10 小时前
opencode-rules 插件
java·开发语言·前端·人工智能·chrome·git·github
柳杉10 小时前
借助 Codex 和可视化工作流,从调研到完整实现,3D 大屏竟然可以这么简单
前端·ai编程·数据可视化