Jotaiメモ
selectAtom
readonlyなderived atomとselectAtomはどちらも同じことができるけど,selectAtomは以前のatomの値と比較して処理が行えるのが違い?
基本的にはderived atomを使用して,それでも回避できないときのみ使用する.
⚠️Unlike its name,
selectAtom
is provided as an escape hatch. Using it means building not 100% pure atom model. Prefer using derived atoms and useselectAtom
only whenequalityFn
orprevSlice
is unavoidable.
splitAtom
配列をatomとして管理すると,その一つの要素を変更したときにほかの要素を参照しているコンポーネントも再レンダリングされてしまう.これを避けるには配列の要素をatomで包むようにする.
splitAtom
を使うと引数に渡した配列のatomに対して各要素をatomで包んだatomを作成してくれる.
const atomList = atom([1, 2, 3]); // PrimitiveAtom<number[]>
const atomsAtom = splitAtom(atomList); // Atom<PrimitiveAtom<number>[]>
配列の子要素だけを変更したときに,memo()
しなくても編集対象外のコンポーネントの再レンダリングが抑制されるのは便利.
useAtom
or useState
コンポーネント内の状態管理にはReact HooksのuseState
を使っても,JotaiのuseAtom
を使っても良い.ただそのコンポーネントの状態を外部で参照する可能性が出てくるかもしれない.それだったら最初からuseAtom
にしてもよいのでは.どうしても限定したければProvider
を使うのも手.
2つの手法を使ってやっていくと面倒くさいので,Jotaiを使っているのなら全部atomで管理したほうが楽そう...
でも,Provider
が大量に作成しないといけない場合は大変なので,React Hooksを使った方がいいかも(リストの要素内の状態管理など)...
あたりまえだけど,Providerの内部のコンポーネントでglobalや上位コンテキストのatomを使用したいときは,その外でuseAtomして値や設定関数を取得しておき,Provider内部のコンポーネントにはイベントハンドラーの形で渡す必要がある.
function Parent(): React.JSX.Element {
const setValue = useSetAtom(globalAtom);
const setFunc = (newValue) => setValue(newValue);
return (
<Provider>
<Child func={setFunc} />
</Provider>
);
}
ローカルなatomになるにはそのuseAtom
が呼び出されているコンポーネント自体をProvider
で囲まないとダメ.
Atom.toString()
atomは一意の値を返すtoString()
メソッドを持つ.map
などでatomに対応した並列コンポーネントを複数作成したときに割り振るkey
プロパティにはこのメソッドが有用.
const atoms = [atom(1), atom(2), atom(3)];
<ul>{ atoms.map((a) => <li key={`${a}`}>{useAtomValue<number>(a)}</li>) }</ul>