iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 21
0
Modern Web

關於React,那些我不知道的系列 第 21

狀態管理的救星?! Recoil 想用參數來切換 state 怎麼辦? ( selectorFamily ) 2

  • 分享至 

  • xImage
  •  

Why selectorFamily?

為什麼我們需要 selectorFamily ? 還記得我們在前面幾堂介紹 atom / selector 如何使用嗎?
我們使用一個 atom 來記錄一個共享狀態「長度」,另外透過 2 個 selector 根據長度變化來計算正方形面積與圓面積。

今天我們將長度存入 Recoil 內,可以直接透過 selector 獲取任何在 Recoil 之內的狀態。在現實應用上,我們有時候不能或不想將某個狀態存入 Recoil ,但又希望某個共享狀態是可以根據外部的狀態做出對應的計算,我們預期以參數的形式帶入 Recoil 讓 Recoil 根據這個參數作出對應的運算、互動,這時候我們就需要 selectorFamily

Codesandbox demo(atom / selector)

const lengthState = atom({
  key: "length",
  default: 0
});
const circularAreaState = selector({
  key: "circularArea",
  get: ({ get }) => {
    return get(lengthState) * get(lengthState) * 3.14;
  }
});

今天假如我們不想把這個 length 長度存入 Recoil,改依賴元件內部 local 狀態,我們可以先把 pi 改成 Recoil 內部共享的 shared state,然後再透過外部帶入半徑的數字,讓 Recoil 內,可以取得外部的 半徑 以及內部共享的 pi。此時我們透過 selectorFamily ,將selector 的 get 屬性 ({get})=>compute(recoil state) 改成 (param)=>({get})=>compute(recoil state with param)
示意如下:

Codesandbox demo(selectorFamily)

const piState = atom({
  key: "pi",
  default: 3.14
});
const circularAreaState = selectorFamily({
  key: "circularArea",
  get: (length) => ({ get }) => {
    return get(piState) * length * length;
  }
});

此時,我們在元件內呼叫 circularAreaState 時,我們一樣是透過 useRecoilValue ,只是此時,我們就可以在我們的 state 後面帶上參數 const circularArea = useRecoilValue(circularAreaState(10)); ,這樣子表示我們帶入參數 10 ,而根據我們在 selectorFamily 內部的定義,我們將會拿 10 * 10 * pi,得到以 10 為半徑的圓面積。

接著,我們將原本 Recoil 共享的shared state 長度 (length) 改為 local state,並將這個 local state 作為參數帶入 Recoil 當中。

const MyComp = () => {
  const [length, setLength] = useState(1);
  const circularArea = useRecoilValue(circularAreaState(length));
  const handleChange = (e) => {
    setLength(e.target.value);
  };
  return (
    <div>
      {`請修改長度`}
      <input type="number" onChange={handleChange} />
      <div>{` 長度 is ${length}`}</div>
      <div>{` 圓面積 is ${circularArea}`}</div>
    </div>
  );
};

Codesandbox demo(selectorFamily)

總結

  1. 當你希望透過外部的參數(無論是你自己得local, context,redux store...)與 Recoil 內部的狀態做互動、運算時,你可以使用 selectorFamily
  2. 你希望同一個 key 可以根據不同條件,儲存許多狀態時,可以使用 selectorFamily

參考資料

Recoil
精讀《recoil》


上一篇
狀態管理的救星?! Recoil 想用參數來切換 state 怎麼辦? ( selectorFamily )
下一篇
如何做一個 銀行/分行的選單 selectorFamily
系列文
關於React,那些我不知道的30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言