提前聲明:以下內(nèi)容基本就是官方文檔的(不正規(guī))翻譯~官方介紹鏈接
特點(diǎn)
- 基于react洋满。添加一些到應(yīng)用程序中踩身,獲得快速靈活的共享狀態(tài)稍浆。
- 數(shù)據(jù)流圖互艾。派生數(shù)據(jù)和異步查詢被純函數(shù)和高效訂閱馴服试和。
- 通過(guò)觀察應(yīng)用程序中的所有狀態(tài)更改來(lái)實(shí)現(xiàn)持久性、路由纫普、時(shí)間旅行調(diào)試或撤消阅悍,而不影響代碼拆分。
使用背景
出于兼容性和簡(jiǎn)便性的考慮,編寫代碼時(shí)最好使用React的內(nèi)置狀態(tài)管理功能节视,而不要使用外部全局狀態(tài)拳锚。但是react有這些缺陷:
- 組件狀態(tài)只能通過(guò)將其提升到公共祖先來(lái)共享,但這可能包括一棵巨大的樹寻行,然后需要整個(gè)公共組件重新渲染霍掺。
- 上下文只能存儲(chǔ)一個(gè)值,且不能存儲(chǔ)不確定的一組值拌蜘,每個(gè)值都需要有自己的使用者杆烁。
- 這兩種方法都使得樹的頂部(狀態(tài)必須存在的地方)很難從樹的葉子(使用狀態(tài)的地方)代碼分割出來(lái)。
recoil優(yōu)點(diǎn)
狀態(tài)變化從該圖的根(我們稱為原子--atom)開(kāi)始简卧,通過(guò)純函數(shù)(我們稱為選擇器--seletor)進(jìn)入組件兔魂。
通過(guò)使用這種方法:
- 獲得了一個(gè)無(wú)樣板的API,其中共享狀態(tài)具有與React本地狀態(tài)相同的簡(jiǎn)單get / set接口(但如果需要贞滨,也可以用reducer等封裝)入热。
- 有可能與并發(fā)模式和其他新的React功能兼容。
- 狀態(tài)定義是增量式和分布式的晓铆,從而可以進(jìn)行代碼拆分勺良。
- 可以用派生數(shù)據(jù)替換狀態(tài),而無(wú)需修改使用它的組件骄噪。
- 派生數(shù)據(jù)可以在同步和異步之間移動(dòng)尚困,而無(wú)需修改使用它的組件。
- 可以將導(dǎo)航視為一流的概念链蕊,甚至可以對(duì)鏈接中的狀態(tài)轉(zhuǎn)換進(jìn)行編碼事甜。
- 以向后兼容的方式持久保存整個(gè)應(yīng)用程序狀態(tài),可以在應(yīng)用程序更改后持久保存的狀態(tài)滔韵。
核心概念
使用Recoil逻谦,您可以創(chuàng)建一個(gè)數(shù)據(jù)流圖,數(shù)據(jù)從atoms(共享狀態(tài))通過(guò)selectors(純函數(shù))一直注入到React組件陪蜻。atoms是組件可以預(yù)訂的狀態(tài)單位邦马。selectors可以同步或異步轉(zhuǎn)換此狀態(tài)。
atoms
atoms是狀態(tài)單位,它們是可更新和可訂閱的,當(dāng)atoms被更新時(shí)宴卖,每個(gè)訂閱的組件都將使用新值重新呈現(xiàn)滋将。它們也可以在運(yùn)行時(shí)創(chuàng)建,可以使用atoms來(lái)代替React本地組件狀態(tài)。如果多個(gè)組件使用相同的原子症昏,則所有這些組件共享其狀態(tài)随闽。
const fontSizeState = atom ({
key:'fontSizeState' ,
default:14 肝谭,
} );
原子需要一個(gè)唯一的key掘宪,該key可用于調(diào)試蛾扇,持久性以及某些高級(jí)API,這些API可讓您查看所有atoms的圖添诉。確保key在全局上是唯一的,像React組件狀態(tài)一樣屁桑,它們也具有默認(rèn)值医寿。
要從組件讀取和寫入原子栏赴,我們使用Hook useRecoilState。就像React一樣useState靖秩,但是現(xiàn)在狀態(tài)可以在組件之間共享:
function FontButton (){
const [ fontSize 须眷,setFontSize ] = useRecoilState(fontSizeState);
return(
<button onClick = { ()=> setFontSize ((size )=> size + 1 )} style = { { fontSize } } >
Click to Enlarge
</ button>
);
}
單擊該按鈕將使按鈕的字體大小增加一,但是現(xiàn)在其他組件也可以使用相同的字體大泄低弧:
seletor
是接受的原子或其它選擇作為輸入的純函數(shù)花颗。當(dāng)這些上游原子或選擇器更新時(shí),seletor函數(shù)將被重新評(píng)估惠拭。組件可以像atoms一樣訂閱到選擇器扩劝,然后在選擇器更改時(shí)將重新渲染。
selector用于計(jì)算基于狀態(tài)的派生數(shù)據(jù)职辅,這使我們避免了冗余狀態(tài)棒呛,通常無(wú)需使用reduce來(lái)保持狀態(tài)同步和有效。取而代之的是域携,最小狀態(tài)集存儲(chǔ)在atoms中簇秒,而其他所有內(nèi)容都根據(jù)該最小狀態(tài)有效地進(jìn)行了計(jì)算,由于選擇器會(huì)跟蹤哪些組件需要他們以及它們所依賴的狀態(tài),因此它們使這種功能方法更加有效秀鞭。
從組件的角度來(lái)看趋观,selector和原子具有相同的接口,因此可以互相替換锋边。
const fontSizeLabelState = selector({
key:'fontSizeLabelState' 皱坛,
get :({ get } )=> {
const fontSize = get(fontSizeState);
const unit = 'px' ;
return ` $ { fontSize } $ { unit } ` ;
} ,
} );
該get屬性是要計(jì)算的函數(shù)豆巨。它可以使用get傳遞給它的參數(shù)訪問(wèn)atoms和其他選擇器的值剩辟。每當(dāng)它訪問(wèn)另一個(gè)原子或選擇器時(shí),就會(huì)創(chuàng)建一個(gè)依賴關(guān)系搀矫,以便更新另一個(gè)原子或選擇器將導(dǎo)致重新計(jì)算該原子或選擇器抹沪。
在此fontSizeLabelState示例中,選擇器具有一種依賴性:fontSizeState atom瓤球。從概念上講融欧,fontSizeLabelState selector的行為就像一個(gè)純函數(shù),將fontSizeState作為輸入并返回格式化的字體大小標(biāo)簽作為輸出卦羡。
可以使用讀取選擇器useRecoilValue()
噪馏,該選擇器將原子或選擇器作為參數(shù)并返回相應(yīng)的值麦到。我們不使用useRecoilState()
,因?yàn)?code>fontSizeLabelState選擇器不可寫.
function FontButton (){
const [ fontSize 欠肾,setFontSize ] = useRecoilState (fontSizeState );
const fontSizeLabel = useRecoilValue (fontSizeLabelState );
return(
< >
< div > Current font size:$ { fontSizeLabel } </ div >
<button onClick = { ()=> setFontSize (fontSize + 1 )} style= { { fontSize } } >
Click to Enlarge
</ button>
</ >
);
}
現(xiàn)在瓶颠,單擊按鈕有兩件事:增加按鈕的字體大小,同時(shí)更新字體大小標(biāo)簽以反映當(dāng)前字體大小刺桃。