速来报名!AICon北京站鸿蒙专场~ 了解详情
写点什么

听说 Signals 快要登陆 React 了?

  • 2024-04-22
    北京
  • 本文字数:2727 字

    阅读完需:约 9 分钟

听说Signals快要登陆React了?

“Signals”专门用于管理客户端状态,而且从最近的趋势来看,其很有可能在 React 中发挥作用。



就在上周,Dashi Kato(Waku 的缔造者)发布了 use-signals,一个面向 TC39 signals 的实验性 React hook,旨在演示 Signals 如何在 React 中发挥作用。



Signals 是什么?


Signals 已然经历约 10 年的发展周期,先后得到 Angular、Vue、SolidJS、Qwik 以及 Preact 等众多 JavaScript 框架的采纳,用于管理客户端状态。Signals 属于能自动跟踪其使用位置的变量。一旦 Signal 发生变更,其值就会失效,进而触发 UI 状态更新 / 重新渲染。


举例来说,这是一个名为 counter 的 Signal,其值为 0。


const counter = new Signal.State(0);
复制代码


需要明确的是,Signals 与 React 的 useState 有着本质区别。useState 是 React 提供的 hook,用于管理功能组件内的状态,并允许开发者声明状态变量并更新该变量的函数。


Signals 则是事件的侦听器或者观察器,用于处理异步事件或是超出组件直接控制之外的数据变更。因此,大家会看到 Signal 声明中并没有定义“setter”函数。但配合 React 之后,情况将大为不同。下面来看之前的 Signal 如何在 React 中进行声明:


const [counter, setCounter] = useState(0);
复制代码


Signals 的概念之所以非常有趣,就是因为 React 那“自上而下”的模型意味着每当有状态值发生变化时,组件树的所有后代都会重新渲染并对 UI 执行相应变更,从而保证 DOM/UI 与应用程序的状态同步。


而在使用 Signals 管理状态之后,开发者能够以更细粒度方式控制对 UI 中的哪些部分进行“重新渲染”。但不要误会,这并不是说 Signals 比 React 方法的性能更高,只是二者的功能定位有所不同。


Signals 使用方法


如上所示,我们可以使用 new 构造函数来声明一个 Signal,例如:


const counter = new Signal.State(0);
复制代码


之后,要“get”一个 Signal 的值,我们可以使用.get() 方法;而要“set”或者更新一个 Signal,我们可以使用.set() 方法。例如:


counter.get();counter.set(10);
复制代码


Signals 在 React 中如何起效?


跟之前提到的 Signals 使用方法不同,它在 React 中另有起效方式。绕过 React 的 diffing 无疑有违 React 声明式编程这一核心原则,因此 React 中的 Signals 仍将使用 VDOM,而且同样会像变更 useState 那样触发重新渲染。


那么在 React 中使用 Signals 还有何意义?其实我的第一反应也是如此,但请大家先别急,让我们一同探索 Signals 的深邃世界。


TC39 提案


如果 TC39 提案获得通过,则意味着 Signals 将在 JavaScript 中原生可用,届时我们将可以在框架之外使用 Signals。更重要的是,框架作者们理论上也能够以标准化方式实现 Signals。换言之,Signals 机制的任何改进都将令所有采用标准化方法的框架受益。而目前,大部分使用 Signals 的框架所采取的处理方式都各有细微差异。


4 月 11 日,Rob Eisenberg 宣布 TC39 提案已经进入第一阶段。这意味着该提案已被纳入 ECMAScript 的考量范围。虽然还有很多工作要做,但这项提案似乎正朝着正确的方向稳步迈进。



TC39 提案还强调了围绕不同框架特定要求的方式开发 API 的重要性。use-signals 的意义也正在于此,它在使用建议 Signals API 的同时,也仍然遵循 React 的核心设计原则。


无论 React 团队最终是否会采纳 Signals,use-signals 的出现都在一定程度上表明 Signals 确实能够在 React 中发挥作用。


Signal Utils 提案


Signals 目前仅支持原语,但也有其他 signal-utils 提案正在推进当中,努力将对象和数组引入其中。例如:


对象


import { SignalObject } from 'signal-utils/object';

let obj = new SignalObject({ isLoading: true, error: null, result: null,});
复制代码


数组


import { SignalArray } from 'signal-utils/array';

let arr = new SignalArray([1, 2, 3]);
复制代码


在 React 中使用 Signals 示例


聊了这么多,下面我们一起来看在 React 中具体如何使用 Signals。这里展示的 React 代码在 Waku 上下文中运行,默认在服务器端进行渲染,但其也能支持纯客户端组件的“use client”指令。


与 useState 不同的是,对 Signals 来说,新的 Signals 声明是在组件外部实现的。在以下代码片段当中,也就是名为 counter 的 const,其用于存储初始值并可以被传递至 useSignal hook。


该 count const 公开了.set() 与.get() 方法,这些方法可以在事件处理函数 handleInc 当中使用。


Signal 值的变更将触发 DOM 更新,并在 UI 中显示新的 count 值。


尤其有趣的一点是,在返回的 Jsx 当中,我们不再需要使用.get() 来访问并显示 HTML  <div/> 元素中的值。相反,现在可以直接访问 count 值。这与 Qwik 的实现略有不同,后者需要我们从 counter 处访问值,例如 counter.value。


'use client';

import { Signal, useSignal } from 'use-signals';

const counter = new Signal.State(0);

const UseSignalComponent = () => { const count = useSignal(counter);

const handleInc = () => counter.set(counter.get() + 1);

return ( <> <div>useSignal count: {count}</div> <button type='button' onClick={handleInc}> Update count </button> </> );};

export default UseSignalComponent;
复制代码


useState 组件


为了直观比较,以下代码的业务逻辑不变、只是用 React 的 useState hook 进行编写。可以看到,二者之间几乎没有区别。


'use client';

import { useState } from 'react';

const UseStateComponent = () => { const [count, setCount] = useState(0);

const handleInc = () => setCount(count + 1);

return ( <> <div>useState count: {count}</div> <button type='button' onClick={handleInc}> Update count </button> </> );};

export default UseStateComponent;
复制代码


混合 Signals


总结来讲,在 React 中实现 Signals 完全具备可行性。虽然 Signals 可能需要一段时间才能在 JavaScript 中获得原生身份,但我个人高度赞赏其蓬勃发展的技术社区对于全新开发方式的探索。感兴趣的朋友不妨持续关注 GitHub repo:++dai-shi/use-signals++。


原文链接


https://thenewstack.io/did-signals-just-land-in-react/


声明:本文为 InfoQ 翻译整理,未经许可禁止转载。


今日好文推荐


德国再次拥抱Linux:数万系统从windows迁出,能否避开二十年前的“坑”?


谷歌大裁员引发元老集体抗议:领导脑袋空空,无能的中层管理团队不断扩大


系统 bug 致百人入狱,砸了 2.8 亿元仍上云失败!二十年了,这家大企业被日本软件坑惨了


“真男人就应该用 C 编程”!用 1000 行 C 代码手搓了一个大模型,Mac 即可运行,特斯拉前 AI 总监爆火科普 LLM


2024-04-22 17:243025

评论

发布
暂无评论
发现更多内容

如何克服嵌入式开发中的各种挑战,构建完善工具链并落地最佳实践?

龙智—DevSecOps解决方案

嵌入式 嵌入式开发

Spring Boot中如何优雅地实现异步调用?

快乐非自愿限量之名

前端 spring-boot

游戏和电商企业活动频繁,华为云网站安全解决方案如何促进业务发展和增长

平平无奇爱好科技

保姆级教程:带你体验华为云测试计划CodeArts TestPlan

华为云开发者联盟

云计算 华为云 华为云开发者联盟 企业号 7 月 PK 榜

华为扫地僧:揭秘IoT+鸿蒙帮助企业突围物联网安全问题

华为云开发者联盟

物联网 华为云 华为云开发者联盟 企业号 7 月 PK 榜

SpringBoot——自定义自动配置与起步依赖

互联网工科生

spring springboot

5年经验,不会Java性能优化,面试原地翻车

程序员小毕

程序员 后端 JVM java面试 Java性能优化

华为云图像识别Image:技术服务提供商的首选

平平无奇爱好科技

提高网站可用性需要真家伙,华为云网站高可用解决方案有何亮点?

平平无奇爱好科技

国产软件崛起,用友引领企业数智化转型新风向

用友BIP

国产替代

揭秘!用友BIP多维数据库:企业数智化的国产利器

用友BIP

复旦大学附属中山医院:利用明道云进行风险管理及器械溯源的实践案例分享

明道云

[杂谈] pdfbox 2.0.28 文字水印移除操作(Acrobat/WPS)

alexgaoyh

Java PDF remove pdfbox text watermarker

低代码云里雾里,如何择优选择,且看这里

高端章鱼哥

低代码 低代码开发 JNPF

中移物联车联网项目,在 TDengine 3.0 的应用

爱倒腾的程序员

涛思数据 tdengine 时序数据库

一文让你从零开始入门 K8s

伤感汤姆布利柏

看北京地铁如何利用数智底座充分发挥数据价值

用友BIP

数智底座

创新引擎加速数字时代:揭秘JNPF平台与云计算的完美共舞!

不在线第一只蜗牛

云计算 低代码 数字化

万物互联时代,互联网企业为什么需要华为云网站安全解决方案?

平平无奇爱好科技

华为云语音交互服务SIS——与人打交道的智慧软件,非常值得一试

平平无奇爱好科技

华为云视频封面&摘要服务:让视频内容更具吸引力

平平无奇爱好科技

华为云CodeArts Artifact 5大特性,揭秘大型企业制品管理面纱

华为云PaaS服务小智

云计算 华为云 华为开发者大会2023

复杂的舆论场,企业该如何保障内容审核安全?

平平无奇爱好科技

蓬勃发展的数智革命:低代码开发平台开启制造业繁荣新纪元!

EquatorCoco

人工智能 低代码 制造业 数智转型

低代码应用开发平台 高效构建业务系统

力软低代码开发平台

第十八届研电赛“安谋科技杯”上海赛区决赛成功举办

脑极体

AI

DevOps|从腾讯TEG CDC解散聊技术中台价值和建设

laofo

DevOps 研发效能 技术中台 组织建设

想要快速上线网站?香港虚拟主机助你一臂之力!

一只扑棱蛾子

香港虚拟主机

自从前端用上了低代码,开发速度直接起飞

伤感汤姆布利柏

分享6个数据可视化软件工具

互联网工科生

数据可视化 可视化软件

听说Signals快要登陆React了?_架构/框架_Paul Scanlon_InfoQ精选文章