反應(yīng)革命:解放React中的副作用函數(shù),解決心智負(fù)擔(dān)難題

在 React 開發(fā)中,我們經(jīng)常面臨三個(gè)心智負(fù)擔(dān):保證狀態(tài)的不可變性、正確執(zhí)行副作用以及規(guī)避不必要的渲染。副作用函數(shù)是其中一個(gè)最大的挑戰(zhàn),當(dāng)副作用開始執(zhí)行時(shí),不確定性因素會(huì)呈指數(shù)型增長,導(dǎo)致開發(fā)過程中需要小心謹(jǐn)慎,否則可能出現(xiàn)奇奇怪怪、難以排查的問題。然而,通過使用兩個(gè)特殊的 React hook:useSyncState 和 useSyncMemo,我們可以顯著改善開發(fā)體驗(yàn)并消除副作用函數(shù)的復(fù)雜性。
在本文中,我們將詳細(xì)介紹 useSyncState 和 useSyncMemo 的用法,以及它們?nèi)绾螏椭覀兿弊饔煤瘮?shù),同時(shí)滿足 React 的開發(fā)規(guī)則。我們將使用一個(gè)名為 react-sync-state-hook 的庫來獲得這兩個(gè) hook,你可以通過 npm 來安裝它。
首先,我們來了解 useSyncState 的原理。該 hook 很簡單,它通過一個(gè)變量保存狀態(tài)的最新值,并生成一個(gè)不可變數(shù)據(jù)代理返回。在重新渲染前,我們可以通過該數(shù)據(jù)代理來獲取新狀態(tài)的副本。下面是 useSyncState 的用法:
在上面的例子中,A 和 setA 的用法與平常使用的 state 和 setState 并無二致,而 curA 則是保存最新狀態(tài)值的副本。它是一個(gè)不可變數(shù)據(jù)的代理,類似于 immer 的 draft。因此,對(duì) curA 進(jìn)行的任何修改都不會(huì)對(duì)狀態(tài)產(chǎn)生影響。我們可以遵循狀態(tài)不可變的原則來修改狀態(tài),示例如下:
無需擔(dān)心傳進(jìn)去的 curA.current 是一個(gè)代理對(duì)象,因?yàn)樵?setA 的內(nèi)部會(huì)自動(dòng)將其解包,狀態(tài)值將被賦予解包后的數(shù)據(jù)。setA 也支持函數(shù)式更新,其參數(shù)是一個(gè)不可變數(shù)據(jù)代理,并且無需通過 .current 調(diào)用,類似于 useImmer 的用法。
接下來,我們介紹 useSyncMemo 的原理。該 hook 通過訂閱 currentState 的 getter 和 setter,來感知依賴項(xiàng)的變化,從而計(jì)算得到重新渲染前的 memo 值。因此,如果需要顯式傳遞依賴項(xiàng),我們需要使用 currentState 作為依賴項(xiàng)。用法如下:
注意:計(jì)算函數(shù)里只有使用 curA 去計(jì)算才能得到實(shí)時(shí)的 curM。在沒有顯式傳遞依賴項(xiàng)的情況下,useSyncMemo 內(nèi)部會(huì)通過 curA 的 getter 去獲取依賴項(xiàng)。
這兩個(gè) hook 的特點(diǎn)讓我們能夠在重新渲染前獲取到最新的狀態(tài)值和計(jì)算值,從而消除副作用函數(shù)的復(fù)雜性。舉個(gè)例子來說明,假設(shè)我們有兩個(gè)異步請(qǐng)求去獲取狀態(tài) A 和 B 的值,然后根據(jù)它們的值做一些計(jì)算。我們可以使用 useSyncState 和 useSyncMemo 來優(yōu)化這個(gè)過程,示例代碼如下:
通過這樣的寫法,我們可以保證在兩個(gè)異步請(qǐng)求之后,根據(jù) A 和 B 的值執(zhí)行副作用函數(shù) todos(),而且計(jì)算次數(shù)減少到 1 次,不論后面我們新增多少個(gè)狀態(tài),都只會(huì)計(jì)算一次,避免了冗余的計(jì)算。
總結(jié)一下,使用 useSyncState 和 useSyncMemo 可以顯著減少 React 開發(fā)中的心智負(fù)擔(dān),消除副作用函數(shù)的復(fù)雜性,并且提高性能。通過消除副作用,我們可以更自由地在組件中執(zhí)行副作用操作,而無需擔(dān)心依賴問題。同時(shí),這兩個(gè) hook 還能幫助我們遵循狀態(tài)不可變性原則,從而更好地管理狀態(tài)的變更。如果你之前的 React 開發(fā)經(jīng)驗(yàn)與這種方式有所不同,不妨試試使用這兩個(gè) hook,相信對(duì)你會(huì)有一定的幫助。

轉(zhuǎn)載 / 合作?
請(qǐng)聯(lián)系