Family
atomFamily
参考: https://github.com/pmndrs/jotai/issues/23
使用方法
atomFamily(initializeAtom, areEqual): (param) => Atom
这将创建一个函数,该函数接受 param
并返回一个原子。
如果它已经被创建,它将从缓存中返回。
initializeAtom
是一个可以返回任何类型的原子(atom()
,atomWithDefault()
,...)的函数。
注意 areEqual
是可选的,它告诉两个参数是否相等(默认为 Object.is
)。
要复制 Recoil's atomFamily/selectorFamily 的类似行为,
请为 areEqual
指定一个 deepEqual 函数。例如:
import { atom } from 'jotai'import { atomFamily } from 'jotai/utils'import deepEqual from 'fast-deep-equal'const fooFamily = atomFamily((param) => atom(param), deepEqual)
TypeScript
原子族的类型将从 initializeAtom 中推断出来。这是一个使用原始原子的典型用法。
import type { PrimitiveAtom } from 'jotai'/*** 这里的 atom(id) 返回一个 PrimitiveAtom<number>* 而 PrimitiveAtom<number> 是一个 WritableAtom<number, SetStateAction<number>>*/const myFamily = atomFamily((id: number) => atom(id)).
你可以使用 TypeScript 泛型明确声明参数、值和原子的 setState 函数的类型。
atomFamily<Param, Value, Update>(initializeAtom: (param: Param) => WritableAtom<Value, Update>, areEqual?: (a: Param, b: Param) => boolean)atomFamily<Param, Value>(initializeAtom: (param: Param) => Atom<Value>, areEqual?: (a: Param, b: Param) => boolean)
如果你想为原始原子明确声明 atomFamily,你需要使用 SetStateAction
。
type SetStateAction<Value> = Value | ((prev: Value) => Value)const myFamily = atomFamily<number, number, SetStateAction<number>>((id: number) => atom(id),)
注意:内存泄漏
在内部,atomFamily 只是一个 Map,其键是 param,其值是原子配置。 除非你明确地删除未使用的参数,否则这将导致内存泄漏。 如果你使用无限数量的参数,这是至关重要的。
有两种方法可以删除参数。
myFamily.remove(param)
允许你删除特定的参数。myFamily.setShouldRemove(shouldRemove)
是注册shouldRemove
函数,该函数立即运行并且当你要从缓存中获取原子时。- shouldRemove 是一个接受两个参数
createdAt
(以毫秒为单位)和param
,并返回一个布尔值的函数。 - 设置
null
将删除先前注册的函数。
- shouldRemove 是一个接受两个参数
示例
import { atom } from 'jotai'import { atomFamily } from 'jotai/utils'const todoFamily = atomFamily((name) => atom(name))todoFamily('foo')// 这将创建一个新的 atom('foo'),或者如果已经创建,则返回它
import { atom } from 'jotai'import { atomFamily } from 'jotai/utils'const todoFamily = atomFamily((name) =>atom((get) => get(todosAtom)[name],(get, set, arg) => {const prev = get(todosAtom)set(todosAtom, { ...prev, [name]: { ...prev[name], ...arg } })},),)
import { atom } from 'jotai'import { atomFamily } from 'jotai/utils'const todoFamily = atomFamily(({ id, name }) => atom({ name }),(a, b) => a.id === b.id,)