const circularAreaState = selector({
key: "circularArea",
get: ({ get }) => {
return get(lengthState) * get(lengthState) * 3.14;
}
});
selector function 有吃 1 個 Object 參數,這個 Object 有幾個屬性,get 這個 Property 是一個用來計算導出數據( derived data ) 的 function,在這個 get function 它可以在裡面透過 get 取得 atoms selectors,當你呼叫 get 時,這個 selector 就會與其它有使用到的 atoms selectors 建立連結,當有裡面有其中一個狀態被更新時,這個 selector 就會被重新計算。
在我的範例當中,圓面積的 selector 就有依賴到一個長度的 atom 。 circularAreaState 的selector的行為就像是pure function一樣,將 lengthState 作為 input 然後 output 出 circularAreaState 。
useRecoilValue() 作為另一個Recoil 官方 API,它的參數是吃一個 atom 或是 selector 然後回傳出那個state最新的數值,我們不使用 useRecoilState() 拿出 circularArea ,因為 circularArea 是不可被寫入的(它是被 length 這個 atom 計算出來的)Selectors 可以使用 useRecoilValue() 。
CodeSandbox Demo
我們希望有一個長度的狀態,然後根據長度,計算出 正方形面積 與 圓面積。
這個範例我們需用一個 state (長度 length) 作為我們的 atom ,然後另外的這兩個 state 是可以藉由 atom 被計算出來的,而且也依賴於 atom ,因此我們使用 selector 來計算出我們的 square area 跟 circular area。
const lengthState = atom({
key: "length",
default: 0
});
const circularAreaState = selector({
key: "circularArea",
get: ({ get }) => {
return get(lengthState) * get(lengthState) * 3.14;
}
});
const squareAreaState = selector({
key: "squareArea",
get: ({ get }) => {
return get(lengthState) * get(lengthState);
}
});
然後我們在需要使用到這 3 個狀態的地方,透過 useRecoilState() 及 useRecoilValue() 取出。
const [length, setLength] = useRecoilState(lengthState);
const circularArea = useRecoilValue(circularAreaState);
const squareArea = useRecoilValue(squareAreaState);
const handleChange = (e) => {
setLength(e.target.value);
};
而我們渲染的畫面如下:
<div>
<input type="number" onChange={handleChange} />
<div>{` 長度 is ${length}`}</div>
<div>{` 正方形面積 is ${squareArea}`}</div>
<div>{` 圓面積 is ${circularArea}`}</div>
</div>
如此,當我們的 input 更新了 length 時,squareArea 及 circularArea 也會一起被更新。