Skip to main content
atomFamily is deprecated and will be removed in v3. Please use the jotai-family package instead.
atomFamily creates a function that returns atoms based on parameters. It’s useful for creating atoms dynamically.

Migration

// Before
import { atomFamily } from 'jotai/utils'

// After
import { atomFamily } from 'jotai-family'
Install: npm install jotai-family

Import

import { atomFamily } from 'jotai/utils'

Signature

function atomFamily<Param, AtomType extends Atom<unknown>>(
  initializeAtom: (param: Param) => AtomType,
  areEqual?: (a: Param, b: Param) => boolean,
): AtomFamily<Param, AtomType>

interface AtomFamily<Param, AtomType> {
  (param: Param): AtomType
  getParams(): Iterable<Param>
  remove(param: Param): void
  setShouldRemove(shouldRemove: ShouldRemove<Param> | null): void
  unstable_listen(callback: Callback<Param, AtomType>): Cleanup
}

Parameters

initializeAtom
(param: Param) => AtomType
required
A function that creates an atom for a given parameter. The same atom instance is returned for equal parameters
areEqual
(a: Param, b: Param) => boolean
Optional equality function to compare parameters. If not provided, uses reference equality (===)

Return Value

Returns an AtomFamily function with these methods:
  • (param) - Returns the atom for the given parameter, creating it if needed
  • getParams() - Returns an iterable of all current parameters
  • remove(param) - Removes the atom for the given parameter
  • setShouldRemove(fn) - Sets a function to automatically remove old atoms
  • unstable_listen(callback) - Listens to atom creation/removal events (unstable API)

Usage Example

import { atom } from 'jotai'
import { atomFamily } from 'jotai/utils'

// Create a family of atoms for user data
const userAtomFamily = atomFamily((userId: number) =>
  atom(async () => {
    const response = await fetch(`/api/users/${userId}`)
    return response.json()
  })
)

function UserProfile({ userId }: { userId: number }) {
  const [user] = useAtom(userAtomFamily(userId))
  return <div>{user.name}</div>
}

// With custom equality
const coordAtomFamily = atomFamily(
  ({ x, y }: { x: number; y: number }) => atom({ x, y }),
  (a, b) => a.x === b.x && a.y === b.y
)

// Managing the family
const family = atomFamily((id: number) => atom(0))

// Get all current parameters
const params = Array.from(family.getParams())

// Remove specific atom
family.remove(123)

// Auto-remove atoms older than 1 hour
family.setShouldRemove((createdAt) => {
  return Date.now() - createdAt > 60 * 60 * 1000
})

Advanced Usage

Listening to Events

const family = atomFamily((id: number) => atom(0))

const cleanup = family.unstable_listen((event) => {
  console.log(event.type, event.param, event.atom)
  // event.type: 'CREATE' | 'REMOVE'
})

// Later
cleanup()

Automatic Cleanup

type ShouldRemove<Param> = (createdAt: number, param: Param) => boolean

// Remove atoms that haven't been created in the last 5 minutes
family.setShouldRemove((createdAt) => {
  return Date.now() - createdAt > 5 * 60 * 1000
})

// Clear the cleanup function
family.setShouldRemove(null)

Notes

  • Atoms are cached and reused for equal parameters
  • The createdAt timestamp is in milliseconds since epoch
  • unstable_listen is for advanced use cases and may change without notice
  • This utility is deprecated; migrate to jotai-family for continued support

Build docs developers (and LLMs) love