Primitives
reatomArray
Creates an atom for ordered collections and adds immutable wrappers around the array operations you usually need in UI state.
This is a good fit for queues, recent items, and any state where order matters but node-level reordering is not the main feature.
Example
// Track a toast queueconst toasts = reatomArray<string>([], 'toasts')
toasts.push('Build finished')toasts.push('New comment')toasts.shift()
toasts() // ['New comment']reatomBoolean
Creates a boolean atom with the most common state transitions already wired in.
Useful for modal visibility, loading switches, feature flags, and other binary UI state.
Example
// Control a dialog visibility flagconst deleteDialogOpen = reatomBoolean(false, 'deleteDialogOpen')
deleteDialogOpen.setTrue()deleteDialogOpen.toggle()deleteDialogOpen.reset()
deleteDialogOpen() // falsereatomEnum
Creates a string atom limited to a fixed set of variants and augments it with enum-specific helpers.
Treat reatomEnum as the default way to model enums in Reatom apps. It keeps the reactive value, runtime validation, generated setter actions, and a stable myEnum.enum object in one place.
Capabilities:
-
Infers a string union from a readonly variants array.
-
Rejects invalid values at runtime.
-
Generates setter actions like
setOpen()orset_open(). -
Exposes
reset()to return to the configured initial variant. -
Exposes
myEnum.enumso UI code, comparisons, and integrations can reuse the
same canonical values without repeating raw strings.
By default the first variant becomes the initial state. Setter names use camelCase, or snake_case when requested.
Example 1
// Use it as the default enum model and reuse ` myEnum.enum ` valuesconst ticketStatus = reatomEnum( ['new', 'inProgress', 'resolved'], 'ticketStatus',)
ticketStatus.set(ticketStatus.enum.inProgress)
if (ticketStatus() === ticketStatus.enum.inProgress) { ticketStatus.setResolved()}
Object.values(ticketStatus.enum)// ['new', 'inProgress', 'resolved']Example 2
// Match backend-style names with ` snake_case ` settersconst deliveryState = reatomEnum( ['not_started', 'in_progress', 'done'], { name: 'deliveryState', format: 'snake_case', initState: 'not_started', },)
deliveryState.set_in_progress()deliveryState.reset()
deliveryState() // 'not_started'reatomLinkedList
Creates a reactive linked list for collections where inserts, removals, and reordering are part of the main workflow.
Each item becomes a node with hidden prev/next links, so you can move or swap existing items without rebuilding the whole collection. You can start from existing nodes, a node factory, or a config with initState / initSnapshot. Use array() when rendering with normal array helpers, key when you need lookup by a stable id, and batch() when importing or reordering many nodes at once.
Example 1
// Build a reorderable upload queueconst uploads = reatomLinkedList( { create: (fileName: string) => ({ fileName, progress: atom(0), }), key: 'fileName', }, 'uploads',)
uploads.create('cover.png')const hero = uploads.create('hero.png')
uploads.move(hero, null)uploads.map().get('cover.png')?.progress.set(100)
uploads.array().map((upload) => ({ fileName: upload.fileName, progress: upload.progress(),}))// [// { fileName: 'hero.png', progress: 0 },// { fileName: 'cover.png', progress: 100 },// ]Example 2
// Keep derived row state in sync with the source orderconst backlog = reatomLinkedList( (title: string) => ({ title }), 'backlog',)const rows = backlog.reatomMap( (task) => ({ title: task.title, expanded: atom(false), }), 'backlogRows',)
const docsTask = backlog.create('Write docs')backlog.create('Ship release')
rows.array()[0].expanded.set(true)backlog.remove(docsTask)
rows.array().map((row) => ({ title: row.title, expanded: row.expanded(),}))// [{ title: 'Ship release', expanded: false }]isLinkedListAtom
Checks whether a value is a linked list atom or a linked-list derivative created by reatomLinkedList.
Example
// Enable drag-and-drop only for linked listsconst canReorder = (value: unknown) => isLinkedListAtom(value) && value().size > 1reatomMap
Creates a map atom for keyed entities, caches, and registries where random access matters more than iteration order.
Use getOrCreate for lazy initialization, and size when you need a cheap derived counter for badges or limits.
Example
// Cache user presence by idconst presenceByUserId = reatomMap<string, { online: boolean }>( [], 'presenceByUserId',)
presenceByUserId.getOrCreate('alice', () => ({ online: false }))presenceByUserId.set('bob', { online: true })presenceByUserId.delete('alice')
presenceByUserId.size() // 1reatomNumber
Creates a number atom with counter-style helpers for incrementing, decrementing, resetting, and generating a random value.
Handy for pagination, retry counters, wizard steps, and other numeric UI state that changes through user actions.
Example
// Track retry attempts for a flaky requestconst retryCount = reatomNumber(0, 'retryCount')
retryCount.increment()retryCount.increment()retryCount.decrement()
retryCount() // 1reatomRecord
Creates an object atom with helpers for shallow updates, key removal, and resetting to the initial snapshot.
This works well for filter panels, drafts, and settings objects where you usually patch a few fields at a time.
Example
// Edit a product filter draftconst filters = reatomRecord( { query: '', onlyInStock: false, sort: 'popular' }, 'filters',)
filters.merge({ query: 'keyboard', onlyInStock: true })filters.omit('sort')filters.reset('query')
filters() // { query: '', onlyInStock: true }reatomSet
Creates a set atom for unique selections and membership checks.
This is a natural choice for selected ids, expanded panels, pinned items, and feature switches that should never contain duplicates.
Example
// Store selected table rowsconst selectedOrderIds = reatomSet<string>([], 'selectedOrderIds')
selectedOrderIds.add('ord-1')selectedOrderIds.toggle('ord-2')selectedOrderIds.toggle('ord-1')
[...selectedOrderIds()] // ['ord-2']reatomString
Creates a string atom with a reset action that restores the initial value.
Useful for search inputs, drafts, route params, and other text state that should be easy to clear back to its starting point.
Example
// Keep a search query draftconst searchQuery = reatomString('', 'searchQuery')
searchQuery.set('reatom linked list')searchQuery.reset()
searchQuery() // ''