Recoil: React官方推出的狀態管理工具
Recoil 是 Facebook 在2020推出的狀態管理 Library,還在實驗階段(不推薦用在大型專案)。雖然不像 redux 有各種神奇的用法,但比起來少了很多固定的語法要寫,使用起來很簡單!
核心概念
一圖以蔽之的概念圖:
Recoil中有兩種 shared state
,都能夠被訂閱、更新:
- atom:
是shared state
的基本單位。 - selector:
為一 pure function ,透過輸入其他的shared state
,輸出成需要的資料(derived data)。在輸入的shared state
更新時才會重新計算。
在shared state
更新時,只有訂閱該 shared state
的元件會重新渲染。
atom()
每個atom
都需要 unique key 和預設值:
1 | const todoList = atom({ |
在component
中,Recoil 提供了幾個 API :
跟useState()
很像,但括號內放入的不是預設值,是atom
。
useRecoilValue()
:取值1
const list = useRecoilValue(todoList);
useSetRecoilState()
:設值
使用這個 hook 時,shared state
改變時component不會重新渲染。1
const setTodos = useSetRecoilState(todoList);
useRecoilState()
:取值及設值1
const [list,setTodos] = useRecoilState(todoList)
useResetRecoilState()
:能將atom
設定為預設值,
selector()
每個selector
也都需要 unique key,以及get
、set
(非必要) method。
以 todoList 為例,有了 todoList 和目前的 filter 狀態,就可以利用selector
計算當前頁面要顯示的資料了。
1 | const filteredTodos = selector({ |
取值和設值都可以透過get
取得其他shared state
的資料。
非同步資料串接
atom
及selector
都可以利用非同步的方式串接資料:
1 | const userID = atom({ |
利用useRecoilValue()
獲得非同步的shared state
時,可以搭配 React 的<Suspense>
使用來製作載入效果。如果不想,Recoil也有另外提供 API :
useRecoilValueLoadable()
useRecoilStateLoadable()
不同於useRecoilValue()
回傳ERROR
或是PROMISE
,這兩個hooks在遇到非同步串接時會回傳含有state
、content
的物件:
key/回傳內容 | 成功 | 失敗 | loading |
---|---|---|---|
state |
'hasValue' |
'hasError' |
'loading' |
content |
回傳的資料 | error object |
Promise |
family系列 ← 覺得很酷
可以帶入外部引數至atom
、selector
中的酷東東。
atomFamily()
有時需要動態產生atom
時,就可以使用atomfamily()
。官方舉了一個例子來講解使用時機:
假設你做的是一個UI編輯頁面,使用者可以動態新增元件、而且每個元件都有自己的大小、顏色、位置⋯⋯等狀態。
這時不能確定需要幾個atom
,又不想把個別元件的樣式全部塞進一個atom
時,應該怎麼辦~?
在官方推薦影片(9:55-12:00)推出時,可能還沒有atomfamily()
這個語法,為了解決問題,大叔透過帶入不重複的引數動態新增atom
:
1 | const itemWithId = memorize(id => atom({ |
現在Recoil提供了更方便的atomFamily()
:
1 | const itemFamily = atomFamily({ |
預設值 除了atom
能放的之外,還能夠放帶有參數且有回傳值的function
:
1 | const itemFamily = atomFamily({ |
selectorFamily(options)
類似selector()
,但更強大的是能帶參數到get
、set
中。
1 | const selectColor = selectorFamily({ |
atomFamily()
的預設值可以放function
,也可以使用selectFamily()
:
1 | const item = atomFamily({ |
同一個selectFamily()
接收到相同的引數時,會回傳相同的selector
實體。
最後一個
別忘了<RecoilRoot>
!可以有複數個<RecoilRoot>
共存,不會互相影響。但若有巢狀的<RecoilRoot>
,最內層會覆蓋外層。
1 | import { RecoilRoot } from 'recoil'; |
參考資料
Recoil: React官方推出的狀態管理工具