国产av一二三区|日本不卡动作网站|黄色天天久久影片|99草成人免费在线视频|AV三级片成人电影在线|成年人aV不卡免费播放|日韩无码成人一级片视频|人人看人人玩开心色AV|人妻系列在线观看|亚洲av无码一区二区三区在线播放

網(wǎng)易首頁(yè) > 網(wǎng)易號(hào) > 正文 申請(qǐng)入駐

React團(tuán)隊(duì)藏了3年的信號(hào)方案,被這7行代碼捅破了

0
分享至


React 19還沒(méi)捂熱,社區(qū)里一組實(shí)驗(yàn)代碼的Star數(shù)已經(jīng)悄悄破了4000。不是新框架,是有人把Signals塞進(jìn)了React——而且沒(méi)動(dòng)一行React源碼。

這事有意思的地方在于:React團(tuán)隊(duì)自己也在搞Signals(就是那個(gè)叫use的Hook),但進(jìn)度慢得像在擠牙膏。社區(qū)等不及了,直接上手造了個(gè)能跑的生產(chǎn)級(jí)方案。今天這篇就是作者系列的第四篇,講清楚一個(gè)關(guān)鍵問(wèn)題——數(shù)據(jù)副作用和UI副作用,到底該誰(shuí)管?

7行代碼,拆出兩條完全不同的生命周期

先看這段被轉(zhuǎn)發(fā)最多的代碼:

// data/heartbeat.ts import { signal } from "../core/signal"; import { createEffect, onCleanup } from "../core/effect"; export const intervalMs = signal(1000); export const heartbeat = signal(null); createEffect(() => { const ms = intervalMs.get(); const id = setInterval(() => { heartbeat.set(new Date()); }, ms); onCleanup(() => clearInterval(id)); });

7行核心邏輯,干了一件React里很別扭的事:讓一個(gè)定時(shí)器跟著數(shù)據(jù)走,而不是跟著組件走。

作者管這叫"數(shù)據(jù)層的心跳"——intervalMs是個(gè)信號(hào),改它的時(shí)候,舊的定時(shí)器自動(dòng)清理,新的自動(dòng)啟動(dòng)。整個(gè)過(guò)程沒(méi)有組件參與,頁(yè)面切走了它還在跑,頁(yè)面切回來(lái)數(shù)據(jù)還是熱的。

對(duì)比React原生的寫(xiě)法,差別立刻顯現(xiàn)。以前你要么把定時(shí)器塞useEffect里跟著組件生死,要么上Redux-Saga、React Query這種重型方案?,F(xiàn)在7行代碼搞定,而且類型安全。

光標(biāo)閃爍:為什么必須用React的useEffect?

作者緊接著拋了另一個(gè)例子,刻意和上面的形成對(duì)照:

// ui/Blinker.tsx export function Blinker({ enabled = true }) { const [on, setOn] = useState(false); useEffect(() => { if (!enabled) return; const id = setInterval(() => setOn(v => !v), 500); return () => clearInterval(id); }, [enabled]); return |; }

同樣是定時(shí)器,這次老老實(shí)實(shí)用了React的useEffect。為什么?


因?yàn)楣鈽?biāo)閃爍是純視覺(jué)行為,它依賴React的渲染周期——enabled prop變了要立刻停,組件卸載要立刻清。這些時(shí)機(jī)必須對(duì)齊React的commit階段,而不是數(shù)據(jù)的任意變更。

作者的原話很直接:「這是純粹的UI/視覺(jué)行為,它的清理時(shí)機(jī)應(yīng)該跟隨React的提交周期?!?/p>

兩個(gè)例子擺在一起,分界線就清楚了:createEffect管數(shù)據(jù)流的生命周期,useEffect管DOM的生命周期。以前這兩件事被混在一個(gè)Hook里,現(xiàn)在物理隔離。

Dashboard組件:兩條河怎么匯到一處

真正用起來(lái)的時(shí)候,開(kāi)發(fā)者面對(duì)的其實(shí)是混合場(chǎng)景??醋髡叩腁pp.tsx:

export function Dashboard() { const lastBeat = useSignalValue(heartbeat); const ms = useSignalValue(intervalMs); return (

Last heartbeat: {lastBeat?.toLocaleTimeString() ?? "—"}

Polling every {ms} ms

這里用了個(gè)叫useSignalValue的橋接Hook——信號(hào)的值被轉(zhuǎn)換成React能消費(fèi)的state,但信號(hào)的訂閱關(guān)系還在數(shù)據(jù)層自己手里。

結(jié)果是:改intervalMs的時(shí)候,createEffect那邊自動(dòng)重跑定時(shí)器,Dashboard組件只收到最新的ms值,不需要關(guān)心定時(shí)器的創(chuàng)建和銷毀。而B(niǎo)linker組件里的光標(biāo),該閃還是閃,該停還是停,兩條線互不干擾。

作者特意強(qiáng)調(diào)了行為差異:Timer polling(createEffect)獨(dú)立于任何組件,頁(yè)面導(dǎo)航時(shí)繼續(xù)運(yùn)行;UI blinking(useEffect)隨組件掛載/卸載創(chuàng)建和清理。

這個(gè)設(shè)計(jì)在解決什么真問(wèn)題?

熟悉React歷史的人知道,useEffect的批評(píng)聲音從來(lái)沒(méi)停過(guò)。Dan Abramov自己寫(xiě)過(guò)一篇《useEffect完整指南》,底下最高贊評(píng)論是"我還是不懂"。

核心矛盾在于:useEffect被迫同時(shí)干兩件事——同步外部系統(tǒng)(數(shù)據(jù)),和同步瀏覽器API(DOM)。這兩件事的時(shí)序要求完全不同,但API長(zhǎng)得一模一樣,依賴數(shù)組的語(yǔ)義還隨場(chǎng)景變化。


Signals方案把第一層抽走了。數(shù)據(jù)相關(guān)的副作用跟著信號(hào)走,有獨(dú)立的創(chuàng)建-更新-銷毀生命周期;UI相關(guān)的副作用留在React里,跟著渲染周期走。兩邊都用onCleanup,但執(zhí)行的時(shí)機(jī)由各自的運(yùn)行時(shí)保證。

這不是什么理論潔癖。作者舉的實(shí)際場(chǎng)景是:一個(gè)輪詢心跳,一個(gè)光標(biāo)閃爍。在生產(chǎn)環(huán)境里,這可能是WebSocket重連策略和加載動(dòng)畫(huà)的關(guān)系,是后臺(tái)同步狀態(tài)和Toast提示的關(guān)系——以前寫(xiě)在一起必然互相干擾,現(xiàn)在可以分開(kāi)測(cè)試、分開(kāi)優(yōu)化。

社區(qū)對(duì)這個(gè)方案的反應(yīng)很分裂。一部分人覺(jué)得終于不用在useEffect里寫(xiě)一堆防御性代碼了,另一部分人擔(dān)心又多了一層概念負(fù)擔(dān)。但Star數(shù)的增長(zhǎng)是真實(shí)的,4000多個(gè)開(kāi)發(fā)者用實(shí)際行動(dòng)投了票。

React官方的Signals實(shí)現(xiàn)還在RFC階段,具體語(yǔ)法變了好幾稿。社區(qū)方案的優(yōu)勢(shì)是現(xiàn)在就可用,而且API設(shè)計(jì)明顯借鑒了Solid.js的成熟經(jīng)驗(yàn)——createEffect、onCleanup、signal.get()/set(),幾乎照搬。

風(fēng)險(xiǎn)也有。這個(gè)方案依賴React的訂閱機(jī)制做橋接,如果官方最終定的API差異太大,遷移成本不會(huì)小。但作者似乎不太在意,系列文章已經(jīng)寫(xiě)到第四篇,每一篇都在補(bǔ)全邊緣場(chǎng)景的處理。

一個(gè)值得注意的細(xì)節(jié):作者的代碼里沒(méi)有任何"魔法"。signal、createEffect都是普通函數(shù),沒(méi)有編譯時(shí)轉(zhuǎn)換,沒(méi)有Babel插件。這意味著你可以逐行調(diào)試,可以在瀏覽器控制臺(tái)里手動(dòng)調(diào)heartbeat.set()看效果。

這種可觀測(cè)性在現(xiàn)在的前端生態(tài)里反而成了稀缺品。太多方案藏在編譯器后面,開(kāi)發(fā)者遇到問(wèn)題只能猜。

回到開(kāi)頭那個(gè)問(wèn)題:React團(tuán)隊(duì)知道社區(qū)在這么干嗎?

知道。React核心成員Andrew Clark去年在Twitter上回復(fù)過(guò)類似方案,說(shuō)"我們也在探索這個(gè)方向,但想確保和并發(fā)特性兼容"。翻譯一下:官方認(rèn)可問(wèn)題存在,但解法要保守。

保守有保守的道理。React的并發(fā)渲染(Concurrent Rendering)讓時(shí)機(jī)問(wèn)題變得極其復(fù)雜,一個(gè)信號(hào)更新如果在渲染中途觸發(fā),會(huì)不會(huì)導(dǎo)致死循環(huán)?會(huì)不會(huì)破壞時(shí)間切片?

社區(qū)方案目前的答案是:createEffect在微任務(wù)隊(duì)列里調(diào)度,故意不和React的渲染幀搶資源。這個(gè) trade-off 犧牲了最低延遲,換來(lái)了安全性。夠不夠用,取決于你的場(chǎng)景。

作者沒(méi)說(shuō)的是:這個(gè)方案已經(jīng)在某個(gè)生產(chǎn)環(huán)境里跑了多久、撐住了多少流量。但代碼的完整度和測(cè)試覆蓋率暗示這不是玩具項(xiàng)目——有完整的TypeScript定義,有React適配層的邊界情況處理,甚至還有和Next.js App Router的兼容說(shuō)明。

如果你現(xiàn)在就想試,作者提供了現(xiàn)成的模板。但更值得觀察的是這個(gè)模式的演化:Signals會(huì)不會(huì)成為React的標(biāo)配?官方和社區(qū)方案最終是合并還是分叉?以及,有多少開(kāi)發(fā)者愿意為了"更干凈的數(shù)據(jù)流"承擔(dān)額外的學(xué)習(xí)成本?

最后一個(gè)問(wèn)題留給正在讀的你:在你的項(xiàng)目里,有多少useEffect其實(shí)是在管數(shù)據(jù)而不是管DOM?數(shù)清楚這個(gè)數(shù)字,可能比選哪個(gè)方案更重要。

特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相關(guān)推薦
熱點(diǎn)推薦
悲催!月入一萬(wàn),想讓妻子結(jié)束產(chǎn)假上班,深圳35歲男子哭訴被痛斥

悲催!月入一萬(wàn),想讓妻子結(jié)束產(chǎn)假上班,深圳35歲男子哭訴被痛斥

火山詩(shī)話
2026-03-27 08:39:57
美國(guó)也攔不??!內(nèi)塔尼亞胡暴走,下達(dá)末日死令,中東真要吃核彈?

美國(guó)也攔不??!內(nèi)塔尼亞胡暴走,下達(dá)末日死令,中東真要吃核彈?

閱識(shí)
2026-03-28 13:10:52
毒殺、自殺還是逃亡,70余年陰謀論是真是假?揭秘希特勒生死之謎

毒殺、自殺還是逃亡,70余年陰謀論是真是假?揭秘希特勒生死之謎

易玄
2026-03-27 12:57:43
張雪峰告別儀式現(xiàn)場(chǎng):遺照被花海包圍,前來(lái)送葬的隊(duì)伍排成長(zhǎng)龍!

張雪峰告別儀式現(xiàn)場(chǎng):遺照被花海包圍,前來(lái)送葬的隊(duì)伍排成長(zhǎng)龍!

悄悄史話
2026-03-28 17:29:17
勇士險(xiǎn)勝!波神28+8首發(fā)第一,格林6+10桑托斯爆發(fā),庫(kù)里也很平靜

勇士險(xiǎn)勝!波神28+8首發(fā)第一,格林6+10桑托斯爆發(fā),庫(kù)里也很平靜

魚(yú)崖大話籃球
2026-03-28 12:39:05
地球上真的缺油嗎?實(shí)際上是多得用不完

地球上真的缺油嗎?實(shí)際上是多得用不完

比利
2026-03-18 21:40:05
泰國(guó)征兵拿張凌赫做廣告 泰陸軍發(fā)言人:支持!

泰國(guó)征兵拿張凌赫做廣告 泰陸軍發(fā)言人:支持!

看看新聞Knews
2026-03-26 21:37:02
陳妍希生圖胖出神圖!裙子被撐到崩線,手臂大腿都是肉走路很爺們

陳妍希生圖胖出神圖!裙子被撐到崩線,手臂大腿都是肉走路很爺們

妙知
2026-03-28 10:09:16
朝鮮戰(zhàn)場(chǎng)繳獲美軍火箭筒,拆解驚覺(jué)技術(shù)差距改寫(xiě)陸軍征程

朝鮮戰(zhàn)場(chǎng)繳獲美軍火箭筒,拆解驚覺(jué)技術(shù)差距改寫(xiě)陸軍征程

嘮叨說(shuō)歷史
2026-03-18 13:40:57
坐實(shí)了!南京,最成功的省會(huì),沒(méi)有之一

坐實(shí)了!南京,最成功的省會(huì),沒(méi)有之一

城市財(cái)經(jīng)
2026-03-28 11:48:40
從18歲開(kāi)始男人不斷,半百了還沒(méi)玩夠,如今卻活成了人生贏家!

從18歲開(kāi)始男人不斷,半百了還沒(méi)玩夠,如今卻活成了人生贏家!

杰絲聊古今
2026-03-28 03:24:23
隨著喀麥隆0-1,F(xiàn)IFA系列賽澳洲站最新積分榜出爐:中國(guó)男足第一

隨著喀麥隆0-1,F(xiàn)IFA系列賽澳洲站最新積分榜出爐:中國(guó)男足第一

側(cè)身凌空斬
2026-03-27 19:03:34
中東,大消息!伊朗軍方稱擊中一艘美軍艦艇

中東,大消息!伊朗軍方稱擊中一艘美軍艦艇

證券時(shí)報(bào)e公司
2026-03-28 18:02:19
郭麒麟白嫖網(wǎng)紅外賣媛!

郭麒麟白嫖網(wǎng)紅外賣媛!

八卦瘋叔
2026-03-28 09:58:03
重磅!2年7500萬(wàn),哈登與騎士續(xù)約協(xié)議曝光,更炸裂的還在后面…

重磅!2年7500萬(wàn),哈登與騎士續(xù)約協(xié)議曝光,更炸裂的還在后面…

煙潯渺渺
2026-03-28 17:03:40
廣東1男子賣豬肉35年,一貧如洗,卻被網(wǎng)友稱為“最富有的人”

廣東1男子賣豬肉35年,一貧如洗,卻被網(wǎng)友稱為“最富有的人”

小怪吃美食
2026-03-28 10:31:51
你們都是什么時(shí)候?qū)δ信麻_(kāi)竅的?網(wǎng)友:果然還是攔不住有心人

你們都是什么時(shí)候?qū)δ信麻_(kāi)竅的?網(wǎng)友:果然還是攔不住有心人

夜深愛(ài)雜談
2026-02-21 21:37:02
賈國(guó)龍燜面店將在上海開(kāi)店!北京門(mén)店飯點(diǎn)排隊(duì)四五十分鐘

賈國(guó)龍燜面店將在上海開(kāi)店!北京門(mén)店飯點(diǎn)排隊(duì)四五十分鐘

北京商報(bào)
2026-03-28 14:27:18
一人睡遍整個(gè)娛樂(lè)圈?司曉迪打響了2026年第一炮

一人睡遍整個(gè)娛樂(lè)圈?司曉迪打響了2026年第一炮

閱毒君
2026-01-05 07:05:06
張雪峰突然離世,生前他這樣評(píng)價(jià)書(shū)法專業(yè),至今發(fā)人深思!

張雪峰突然離世,生前他這樣評(píng)價(jià)書(shū)法專業(yè),至今發(fā)人深思!

書(shū)法網(wǎng)
2026-03-26 17:35:11
2026-03-28 18:44:49
閃存獵手
閃存獵手
全網(wǎng)蹲好價(jià)的野生捕手,算力與羊毛都不可辜負(fù)。
357文章數(shù) 1關(guān)注度
往期回顧 全部

科技要聞

遭中國(guó)學(xué)界"拉黑"后,這家AI頂會(huì)低頭道歉

頭條要聞

特朗普:北約沒(méi)支持美打擊伊朗 美國(guó)以后也不會(huì)幫北約

頭條要聞

特朗普:北約沒(méi)支持美打擊伊朗 美國(guó)以后也不會(huì)幫北約

體育要聞

“我是全家最差勁的運(yùn)動(dòng)員”

娛樂(lè)要聞

王一博改名上熱搜!個(gè)人時(shí)代正式開(kāi)啟!

財(cái)經(jīng)要聞

臥底"科技與狠活"培訓(xùn):化工調(diào)味劑泛濫

汽車要聞

置換補(bǔ)貼價(jià)4.28萬(wàn)起 第五代宏光MINIEV正式上市

態(tài)度原創(chuàng)

教育
時(shí)尚
房產(chǎn)
藝術(shù)
本地

教育要聞

AI+教師發(fā)展公益行暨第二屆全國(guó)“英語(yǔ)讀思言”及成果展評(píng)研討會(huì)在福建泉州成功舉辦

龍蝦來(lái)了,厭蠢癥炸了

房產(chǎn)要聞

6.8萬(wàn)方!天河員村再征地,金融城西區(qū)開(kāi)發(fā)全面提速

藝術(shù)要聞

這位富二代寫(xiě)的草書(shū),據(jù)說(shuō)康生臨摹500多遍

本地新聞

在濰坊待了三天,沒(méi)遇到一個(gè)“濰坊人”

無(wú)障礙瀏覽 進(jìn)入關(guān)懷版