渡一教育吧 关注:215贴子:1,542
  • 4回复贴,共1

译文:Signals 如何在可维护性和性能上优于 useEffect?

只看楼主收藏回复

文章链接:https://medium.com/zeroonebytes/how-signals-beat-useeffect-in-clean-code-and-performance-9cd37b87b4ea
翻译:谢杰
审校:谢杰
Hi!如果你曾花费数小时调试 useEffect 的依赖数组、追踪无限循环,或者困惑于组件为何频繁重新渲染——那你并不孤独,有很多人和你有相似的经历。现在登场的 Signals,是一种响应式的新方式,正在以极致的精准性和飞快的速度重塑我们管理 state 和副作用的方式。


IP属地:黑龙江1楼2025-06-24 10:03回复
    Signals 更轻量、可预测、速度极快。
    本篇文章将探讨为什么 Signals 是 React 开发的未来,它的出现如何让 useEffect 相形见绌,并且带来了更简洁的代码、更强劲的性能,以及更简单的思维模型。
    我们将通过实际示例进行对比,展示 Signals 如何实现更简洁的代码和更快速的应用表现。通过这些例子,你将看到为什么 Signals 在 state 和副作用管理上是一次变革性升级。


    IP属地:黑龙江2楼2025-06-25 17:01
    回复
      2025-09-29 09:25:11
      广告
      不感兴趣
      开通SVIP免广告
      Hooks:React 的主力工具
      React Hooks 彻底革新了函数组件的写法,使得我们无需类组件的复杂性,就能实现 state 管理(useState)、副作用处理(useEffect)以及性能优化计算(useMemo)。
      但在大型应用中,Hooks 往往会带来以下问题:
      渲染过载:组件树层级较深时,频繁的重新渲染会导致 UI 性能下降。
      依赖地狱:useEffect 和 useMemo 的依赖数组越来越复杂,极易引入 bug。
      代码复杂度增加:跨组件管理 state 和副作用通常需要引入 Redux 或 Zustand 等库,带来额外开销。
      Signals:为可扩展性而生
      Signals 是一种细粒度的响应式系统,能以极高的效率管理 state。与 React 的 useState 不同,useState 每次变更都会触发整个组件重新渲染,而 Signals 只会更新依赖它们的那部分 UI,实现精准更新。
      Signals 是轻量且自包含的状态单元。当它们的值发生变化时,会通知所有订阅者(例如你的 UI 或业务逻辑),而不会连带触发整个组件的重新渲染周期。
      import { signal } from'@preact/signals-react';
      constcount=signal(0); // Create a signal
      console.log(count.value); // Read: 0
      count.value=5; // Write: Updates subscribers
      下面是一个来自于 CodeSandbox 的具体示例。
      示例链接:https://codesandbox.io/p/sandbox/react19-signals-101-s3q37h?file=%2Fsrc%2FApp.js%3A30%2C20&from-embed
      [!tip]
      译者备注:请务必打开 CodeSandbox 查看示例代码
      在上面的示例中,点击第一个按钮时,你会在控制台日志中看到两个子组件都被重新渲染了。而当你点击第二个按钮时,只有 ChildY 组件被渲染。原因在于,第一个按钮更新的是 React 的 state,而第二个按钮更新的是 Signal。由于 Signal 只在 ChildY 中被使用,因此只有该组件被触发渲染。
      Signals 更具可扩展性,原因在于它们:
      消除不必要的重新渲染:只更新依赖的 DOM 节点或计算逻辑,而非整个组件。
      简化副作用管理:自动追踪依赖,告别手动维护依赖数组。
      提升可维护性:将 state 和逻辑集中管理,降低大型代码库的复杂度。


      IP属地:黑龙江3楼2025-06-25 17:05
      回复
        useEffect 的痛点不容忽视
        useEffect 是 React 处理副作用的核心手段,常用于数据请求、事件监听器或 DOM 操作等场景。但这把“双刃剑”也带来了不少问题:
        依赖数组困境:漏写依赖会导致数据陈旧或出现 bug;写得太多又会导致副作用频繁触发。
        冗长的代码:即使是简单的副作用逻辑,也会变成大量样板代码,让组件变得杂乱无章。
        性能隐患:由于 useEffect 依赖于 React 的渲染周期,可能会触发不必要的重新渲染或清理操作,拖慢应用性能。
        Signals:简洁、响应式、面向未来
        Signals 颠覆了传统模式,将 state 更新从渲染流程中解耦。它们能够自动追踪依赖,仅在必要时触发副作用,并且只更新真正受影响的部分:无需依赖数组,也没有重新渲染的额外开销。
        下面是一个来自于 CodeSandbox 的具体示例。
        示例链接:https://codesandbox.io/p/sandbox/react19-signals-102-gj95ss?file=%2Fsrc%2FApp.js&from-embed
        [!tip]
        译者备注:请务必打开 CodeSandbox 查看示例代码
        为什么这是一次颠覆式的变革?
        无需依赖数组:副作用会自动追踪 signalVariable.value,无需手动维护依赖列表。
        组件更简洁:Signals 存在于组件外部,减少样板代码,逻辑更清晰。
        精准更新:只有绑定了 signalVariable.value 的 DOM 节点会被更新,不会触发整组件的重新渲染。
        这段代码更简洁,也更直观。但它的性能表现如何?答案是:非常出色。


        IP属地:黑龙江4楼2025-06-25 17:06
        回复
          可扩展性对比:useEffect vs. Signals
          我们从几个关键维度来对比 Signals 和 Hooks 在大型 React 应用中的表现:
          1. 性能表现
          Hooks:通过 useState 修改 state 会触发整个组件重新渲染,在组件树较深时可能引发级联更新。useEffect 依附于 React 的渲染周期,state 更新会触发虚拟 DOM 对比、组件重新渲染以及副作用的重新执行。
          Signals:采用细粒度更新机制,仅更新真正依赖的数据节点。对于高频 state 更新的大型应用(如实时看板或协作编辑器),这是一项颠覆性的优化。
          💡 示例:在一个任务看板组件中包含搜索框、下拉选择和列表组件。如果使用 Hooks 更新搜索条件,整个组件会重新渲染,包括 <select> 和其他无关的 DOM。而使用 Signals,仅 <input> 和 <ul> 会更新,大幅节省 CPU 资源。
          2. 可维护性
          Hooks:随着组件复杂度提升,useEffect 和 useMemo 中的依赖数组变得脆弱。新增 state 或副作用时通常需要重构依赖列表,容易引入 bug。
          Signals:自动追踪依赖,无需手动维护数组。同时,外部定义的 Signals 也让组件内部逻辑更简洁。对于大型代码库的重构与扩展更为友好。
          💡 示例:如果为 Hooks 实现版本新增一个筛选条件(比如优先级),需要将 [filter, search] 更新为 [filter, search, priority]。而在使用 Signals 时,副作用会自动适配新依赖,无需改动数组。
          3. 开发体验
          Hooks:在小型应用中较为直观,但大型项目通常需引入 Redux、Zustand 等外部状态管理库以应对复杂度,增加了学习成本和样板代码。
          Signals:提供统一的 state 和副作用模型,减少对外部库的依赖。响应式范式对于动态 UI 更加自然,提升开发效率。
          💡 示例:如果要将任务看板扩展为支持实时任务更新的功能,使用 Hooks 可能需要配置 WebSocket 和 Redux,而使用 Signals,仅需一个副作用逻辑即可实现,保持代码轻量清晰。
          Signals vs. useEffect:如何选择?
          Signals 功能强大,但并非万能解决方案。适用场景如下:
          ✅ 适合使用 Signals 的情况:
          频繁更新的响应式 state(例如:表单、计数器)
          与特定值关联的副作用(例如:API 请求、日志记录)
          性能敏感、状态复杂的应用场景
          🔧 适合使用 useEffect 的情况:
          生命周期相关的任务(例如:组件挂载时初始化 canvas)
          简单副作用,基于渲染逻辑即可满足需求
          尚未接入或不打算引入 Signals 的代码库
          为什么 Signals 是未来趋势?
          Signals 不只是更好的 useEffect,它代表的是一种范式转变。随着 Web 应用朝着实时化、高性能方向发展,Signals 正日益成为主流。原因如下:
          更简单的思维模型:无需与渲染周期或依赖数组纠缠,响应式 state 行为完全符合预期。
          更强的可扩展性:在大型应用中,细粒度更新能有效避免性能瓶颈,尤其适合处理复杂 state。
          生态加速发展:从 Solid.js 到 Qwik,Signals 正在被广泛采用;而像 @preact/signals-react 等项目也在为 React 带来无缝集成。
          更好的开发体验:更简洁的代码带来更快的调试、更轻松的重构和更高效的团队协作。
          相比之下,useEffect 更像是一个“传统工具”——虽然强大,但在如今这个对性能和精准度要求极高的环境中,显得笨重而低效。


          IP属地:黑龙江5楼2025-06-25 17:07
          回复