JotaiJotai

状態
Primitive and flexible state management for React

atomFamily

引用: https://github.com/pmndrs/jotai/issues/23

使用

atomFamily(initializeAtom, areEqual): (param) => Atom

这将创建一个接受 param 并返回一个原子的函数。 如果它已经创建,它将从缓存中返回。 initializeAtom 是可以返回任何类型原子的函数(atom()atomWithDefault() 等)。 请注意,areEqual 是可选的,它判断两个参数是否相等(默认为 Object.is)。

要重现与 Recoil 的 atomFamily/selectorFamily 类似的行为, 为 areEqual 指定一个 deepEqual 函数。 例如:

import { atom } from "jotai";
import deepEqual from "fast-deep-equal";
const fooFamily = atomFamily((param) => atom(param), deepEqual);

TypeScript

原子家族类型将从 initializeAtom 中推断出来。 这是原始原子的典型用法。

import type { PrimitiveAtom } from 'jotai'
/**
* 这里的 atom(is) 返回一个 Primitive Atomic<number>
* 而 Primitive Atom<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,它的键是一个参数,它的值是一个原子配置。 除非您明确删除未使用的参数,否则会导致内存泄漏。 如果您使用无限数量的参数,这一点至关重要。

有两种方法可以删除参数。

  • myFamily.remove(param) 允许您删除特定参数。
  • myFamily.setShouldRemove(shouldRemove) 是注册 shouldRemove 函数,它会在您从缓存中获取原子时立即运行。
    • shouldRemove 是一个函数,它接受两个参数 createdAt(以毫秒为单位)和 param,并返回一个布尔值。
    • 设置 null 将删除之前注册的函数。

示例

import { atom } from "jotai";
import { atomFamily } from "jotai/utils";
const todoFamily = atomFamily((name) => atom(name));
todoFamily("foo");
// 这将创建一个新的 atom('foo'),或者返回已经创建的那个```
```js
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);
return { ...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
);

Codesandbox