Family
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 { atomFamily } from 'jotai/utils'import deepEqual from 'fast-deep-equal'const fooFamily = atomFamily((param) => atom(param), deepEqual)
TypeScript
atom family의 타입은 initializeAtom에서 추론됩니다. 다음은 기본 원자(primitive atom)를 사용한 일반적인 예제입니다.
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)
기본 원자(primitive atom)에 대해 atomFamily를 명시적으로 선언하려면 SetStateAction
을 사용해야 합니다.
type SetStateAction<Value> = Value | ((prev: Value) => Value)const myFamily = atomFamily<number, number, SetStateAction<number>>((id: number) => atom(id),)
주의: 메모리 누수
내부적으로 atomFamily는 키가 파라미터이고 값이 atom 설정인 Map입니다.
사용하지 않는 파라미터를 명시적으로 제거하지 않으면 메모리 누수가 발생할 수 있습니다.
이 문제는 무한한 수의 파라미터를 사용할 때 특히 중요합니다.
파라미터를 제거하는 방법은 두 가지가 있습니다.
myFamily.remove(param)
을 사용하면 특정 파라미터를 제거할 수 있습니다.myFamily.setShouldRemove(shouldRemove)
는shouldRemove
함수를 등록하는 방법입니다. 이 함수는 즉시 실행되며, 캐시에서 atom을 가져오려고 할 때도 실행됩니다.shouldRemove
는 밀리초 단위의createdAt
과param
두 가지 인자를 받고, 불리언 값을 반환하는 함수입니다.null
을 설정하면 이전에 등록된 함수가 제거됩니다.
예제
import { atom } from 'jotai'import { atomFamily } from 'jotai/utils'const todoFamily = atomFamily((name) => atom(name))todoFamily('foo')// 이 코드는 새로운 atom('foo')를 생성하거나, 이미 생성된 경우 해당 atom을 반환합니다.
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,)