selectAtom
引用: https://github.com/pmndrs/jotai/issues/36
function selectAtom<Value, Slice>(anAtom: Atom<Value>,selector: (v: Value) => Slice,equalityFn: (a: Slice, b: Slice) => boolean = Object.is): Atom<Slice>;
此函数创建一个派生原子,其值是原始原子值的函数,由 selector
确定。
只要原始原子发生变化,选择器函数就会运行; 仅当 equalityFn
通知派生值已更改时,它才会更新派生原子。
默认情况下,equalityFn
是引用相等性,但您可以提供您最喜欢的 deep-equals 函数以在必要时稳定派生值。
示例
const defaultPerson = {name: {first: "Jane",last: "Doe",},birth: {year: 2000,month: "Jan",day: 1,time: {hour: 1,minute: 1,},},};// 原始原子。const personAtom = atom(defaultPerson);// 跟踪 person.name。 当 person.name 对象更改时更新// 即使 name.first 和 name.last 都没有实际更改。const nameAtom = selectAtom(personAtom, (person) => person.name);// 跟踪 person.birth。 在年、月、日、小时或分钟更改时更新。// 使用 deepEquals 意味着如果 birth 字段被替换为包含相同数据的新对象,则此原子不会更新。 例如,如果从数据库中重新读取人。const birthAtom = selectAtom(personAtom, (person) => person.birth, deepEquals);
保持稳定的引用
与往常一样,为了防止在渲染周期中使用 useAtom 时出现无限循环,您必须为 useAtom 提供原子的稳定引用。
对于 selectAtom
,我们需要 基础原子和选择器都 稳定。
const [value] = useAtom(selectAtom(atom(0), (val) => val)); // 所以这会导致无限循环
为了满足这些约束,您有多种选择:
const baseAtom = atom(0); // Stableconst baseSelector = (v) => v; // Stableconst Component = () => {// 解决方案 1:使用“useMemo”记忆整个结果原子const [value] = useAtom(useMemo(() => selectAtom(baseAtom, (v) => v), []));// 解决方案 2:使用“useCallback”记忆内联回调const [value] = useAtom(selectAtom(baseAtom,useCallback((v) => v, [])));// 解决方案 3:所有约束都已满足const [value] = useAtom(selectAtom(baseAtom, baseSelector));};