Documentation Index Fetch the complete documentation index at: https://mintlify.com/reatom/reatom/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The action() function creates a container for complex logic, side effects, and orchestration of multiple state updates. Unlike atoms, actions are meant to be called with parameters and can return values. Actions have atom-like features (subscribe, extend) and track their call history.
Import
import { action } from '@reatom/core'
Signature
function action < Params extends any [], Payload >(
cb : ( ... params : Params ) => Payload ,
name ?: string
) : Action < Params , Payload >
function action < Param , Payload >(
cb : (() => Payload ) | (( param ?: Param ) => Payload ),
name ?: string
) : Action <[ Param ? ], Payload >
function action < T extends Fn >(
cb : T ,
name ?: string
) : GenericAction < T >
Parameters
cb
(...params: Params) => Payload
required
The function containing the action’s logic. It can accept any parameters and return any value. The function can be synchronous or asynchronous.
Optional name for the action. Useful for debugging and dev tools. If not provided, an auto-generated name based on the function name will be used.
Returns
An action instance with the following interface: (...params)
(...params: Params) => Payload
Call the action with parameters to execute its logic. Returns the payload.
subscribe
(cb?: (state: ActionState<Params, Payload>) => any) => Unsubscribe
Subscribe to action calls. The callback receives an array of action calls with their params and payload. The state is automatically cleared after each transaction.
Apply extensions to add functionality to the action. See extend() for details.
Examples
Basic Action
import { action } from '@reatom/core'
const greet = action (( name : string ) => {
return `Hello, ${ name } !`
}, 'greet' )
const message = greet ( 'Alice' ) // -> "Hello, Alice!"
State Updates in Actions
import { atom , action } from '@reatom/core'
const count = atom ( 0 , 'count' )
const lastUpdate = atom ( '' , 'lastUpdate' )
const increment = action (( amount : number = 1 ) => {
count . set ( count () + amount )
lastUpdate . set ( new Date (). toISOString ())
return count ()
}, 'increment' )
increment () // -> 1
increment ( 5 ) // -> 6
count () // -> 6
Async Actions
import { action , atom , wrap } from '@reatom/core'
const userData = atom ( null , 'userData' )
const isLoading = atom ( false , 'isLoading' )
const fetchUser = action ( async ( userId : string ) => {
isLoading . set ( true )
try {
const response = await wrap ( fetch ( `/api/users/ ${ userId } ` ))
const data = await wrap ( response . json ())
userData . set ( data )
return data
} finally {
isLoading . set ( false )
}
}, 'fetchUser' )
await fetchUser ( '123' )
Subscribing to Actions
const addItem = action (( item : string ) => {
console . log ( 'Adding:' , item )
return item
}, 'addItem' )
addItem . subscribe (( state ) => {
console . log ( 'Action called:' , state )
})
// Logs immediately: "Action called: []"
addItem ( 'apple' )
// Logs: "Adding: apple"
// Then after transaction: "Action called: [{ params: ['apple'], payload: 'apple' }]"
addItem ( 'banana' )
// Logs: "Adding: banana"
// Then after transaction: "Action called: [{ params: ['banana'], payload: 'banana' }]"
No Arguments Action
let counter = 0
const tick = action (() => {
counter ++
return counter
}, 'tick' )
tick () // -> 1
tick () // -> 2
tick () // -> 3
Complex Action Logic
interface TodoItem {
id : string
text : string
completed : boolean
}
const todos = atom < TodoItem []>([], 'todos' )
const filter = atom < 'all' | 'active' | 'completed' >( 'all' , 'filter' )
const addTodo = action (( text : string ) => {
const newTodo : TodoItem = {
id: crypto . randomUUID (),
text ,
completed: false
}
todos . set ([ ... todos (), newTodo ])
return newTodo
}, 'addTodo' )
const toggleTodo = action (( id : string ) => {
todos . set (
todos (). map ( todo =>
todo . id === id
? { ... todo , completed: ! todo . completed }
: todo
)
)
}, 'toggleTodo' )
const clearCompleted = action (() => {
const active = todos (). filter ( todo => ! todo . completed )
todos . set ( active )
return active . length
}, 'clearCompleted' )
addTodo ( 'Buy milk' )
addTodo ( 'Walk the dog' )
toggleTodo ( todos ()[ 0 ]. id )
clearCompleted () // -> 1
Actions with Error Handling
const riskyAction = action ( async ( shouldFail : boolean ) => {
if ( shouldFail ) {
throw new Error ( 'Action failed' )
}
return 'Success'
}, 'riskyAction' )
try {
await riskyAction ( true )
} catch ( error ) {
console . error ( 'Caught:' , error . message ) // -> "Caught: Action failed"
}
const result = await riskyAction ( false ) // -> "Success"
Action Middleware
import { action , withActionMiddleware } from '@reatom/core'
// Create a logging middleware
const withLogging = withActionMiddleware (( target ) => {
return ( next , ... params ) => {
console . log ( `[ ${ target . name } ] Called with:` , params )
const result = next ( ... params )
console . log ( `[ ${ target . name } ] Returned:` , result )
return result
}
})
const calculate = action (( a : number , b : number ) => {
return a + b
}, 'calculate' ). extend ( withLogging )
calculate ( 2 , 3 )
// Logs: "[calculate] Called with: [2, 3]"
// Logs: "[calculate] Returned: 5"
Action Interface
interface Action < Params extends any [] = any [], Payload = any >
extends AtomLike < ActionState < Params , Payload >, Params , Payload > {}
ActionState Interface
interface ActionState < Params extends any [] = any [], Payload = any >
extends Array < ActionCall < Params , Payload >> {}
interface ActionCall < Params extends any [], Payload > {
params : Params
payload : Payload
}
GenericAction Type
type GenericAction < T extends Fn > = T & Action < Parameters < T >, ReturnType < T >>
Key Characteristics
Non-Reactive : Actions are not reactive atoms - they don’t track dependencies
Call History : Actions maintain a state array of all calls with their parameters and payloads
Auto-Cleanup : The action state is automatically cleared after each transaction
Subscribable : Actions can be subscribed to track when they’re called
Extensible : Actions support the same extension system as atoms