Package @reatom/methods
Method is special API which works only in Reatom context frame, like action or atom. Some methods are reactive and may work only in reactive context (in atom). Some methods are isomorphic and can be used both in reactive and non-reactive context. Some methods may change the type of context, like peek for none reactive atom reading or wrap for context binding.
Classes
AbortVariable
Defined in: packages/core/src/methods/abortVar.ts:43
Interface for context variables in Reatom
Variables maintain values within the context of a computation tree, allowing for context-aware state similar to React’s Context API but with more granular control and integration with Reatom’s reactive system.
See
https://github.com/tc39/proposal-async-context?tab=readme-ov-file#asynccontextvariable
Extends
Variable<ReatomAbortController, [AbortController?]>
Constructors
Constructor
new AbortVariable():
AbortVariable
Defined in: packages/core/src/methods/abortVar.ts:63
Returns
Overrides
Properties
_findReactiveStartIndex
protected_findReactiveStartIndex:number=1
Defined in: packages/core/src/methods/abortVar.ts:47
Overrides
Variable._findReactiveStartIndex
create()
protectedcreate: (…params) =>ReatomAbortController
Defined in: packages/core/src/methods/variable.ts:30
Parameters
params
…[AbortController?]
Returns
Inherited from
name
readonlyname:`var#${string}`
Defined in: packages/core/src/methods/variable.ts:32
Inherited from
run
run:
GenericAction<<Params,Payload>(value,cb, …params) =>Payload>
Defined in: packages/core/src/methods/variable.ts:97
Executes a callback function with the variable set to a specific value within that execution context
This method creates a new frame in the context tree where the variable is
bound to the provided value. The callback function runs within this frame,
allowing any code inside (and its descendants) to access this value via
get().
Example
const userVar = variable<string>('user')
userVar.run('Alice', () => { console.log(userVar.get()) // 'Alice' })
// Passing parameters to callback const result = userVar.run('Bob', (x, y) => x + y, 2, 3) console.log(result) // 5Template
Types of parameters passed to the callback
Template
Return type of the callback
Param
The value to set for this variable during callback execution. Cannot be undefined.
Param
The callback function to execute with the variable set
Param
Additional parameters to pass to the callback
Returns
The return value of the callback
Throws
If value is undefined
Inherited from
spawn
spawn:
GenericAction<<Params,Payload>(cb, …params) =>Payload>
Defined in: packages/core/src/methods/variable.ts:122
This utility allow you to start a function which will NOT follow the async context of this variable.
Example
// If you want to start a fetch when the atom gets a subscription, // but don't want to abort the fetch when the subscription is lost to save the data anyway. const some = atom('...').extend( withConnectHook((target) => { abortVar.spawn(async () => { // here `wrap` doesn't follow the connection abort const data = await wrap(api.getSome()) some(data) }) }), )Inherited from
Methods
find()
find<
Result>(cb?,frame?):undefined|Result
Defined in: packages/core/src/methods/abortVar.ts:49
Traverses the frame tree to find and map the variable value.
Type Parameters
Result
Result = ReatomAbortController
Return type of the callback
Parameters
cb?
(payload) => undefined | Result
Optional transformation callback
frame?
Frame<any, any[], any>
Optional frame to check (defaults to current top frame)
Returns
undefined | Result
The transformed value or undefined if not found
Overrides
first()
first(
frame):undefined|ReatomAbortController
Defined in: packages/core/src/methods/variable.ts:139
Gets the variable value from the first frame only, without traversing the whole frame tree
Unlike get() which searches through parent frames, this method only
checks the top frame. Returns undefined if the variable is not set in the
frame.
Parameters
frame
Frame<any, any[], any> = ...
Returns
undefined | ReatomAbortController
The value in the frame, or undefined if not set
Inherited from
get()
get(
frame?):undefined|ReatomAbortController
Defined in: packages/core/src/methods/variable.ts:63
Gets the passed frame value of the variable
Parameters
frame?
Frame<any, any[], any>
Optional frame to check (defaults to current top frame)
Returns
undefined | ReatomAbortController
The current value
Throws
If the variable is not found in the frame tree
Inherited from
has()
has(
frame?):boolean
Defined in: packages/core/src/methods/variable.ts:150
Checks if the variable exists in the passed frame stack
Parameters
frame?
Frame<any, any[], any>
Optional frame to check (defaults to current top frame)
Returns
boolean
True if the variable exists in the context
Inherited from
set()
set(…
params):ReatomAbortController
Defined in: packages/core/src/methods/variable.ts:195
Sets a new variable value for CURRENT frame. Be aware that it is mostly for internal use!
Parameters
params
…[AbortController?]
Parameters passed to the setter function
Returns
The new value
Inherited from
subscribe()
subscribe(
cb?):AbortSubscription
Defined in: packages/core/src/methods/abortVar.ts:122
Subscribes to abortion events from parent context tree (including current frame).
Creates a subscription that listens for abort signals from any parent AbortController in the context tree. When an abort occurs, the callback is invoked with the abort error and the subscription automatically cleans up.
It is IMPORTANT to clean up the subscription when it is no longer needed,
otherwise a memory leak will occur. You can use the unsubscribe function
returned by this method or using statement.
Parameters
cb?
(error) => void
Callback invoked when abortion occurs
Returns
Subscription object
Examples
const myResource = computed(async () => { const { controller, unsubscribe } = abortVar.subscribe() const { signal } = controller
try { const response = await fetch('/api/my-resource', { signal }) return await response.json() } finally { unsubscribe() } }).extend(withAsyncData())const myResource = computed(async () => { using { controller } = abortVar.subscribe() const { signal } = controller
const response = await fetch('/api/my-resource', { signal }) return await response.json() }).extend(withAsyncData())throwIfAborted()
throwIfAborted():
void
Defined in: packages/core/src/methods/abortVar.ts:174
NOTE: this method already used in wrap, that you should use in your code
instead.
Throws if any AbortController in the parent context (frame) tree, including the current frame, is aborted.
Returns
void
Throws
ReatomAbortController
Defined in: packages/core/src/methods/abortVar.ts:16
Version of abort controller with explicit name for better debugging.
May control variable propagation by setting the spawned flag (used
internally to handle abort boundaries).
Param
The name of the abort controller
Param
Whether to traverse the frame tree beyond the current frame
(default: false)
Extends
AbortController
Constructors
Constructor
new ReatomAbortController(
name,spawned):ReatomAbortController
Defined in: packages/core/src/methods/abortVar.ts:17
Parameters
name
string
spawned
boolean = false
Returns
Overrides
AbortController.constructor
Properties
name
name:
string
Defined in: packages/core/src/methods/abortVar.ts:18
signal
readonlysignal:AbortSignal
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.dom.d.ts:2723
The signal read-only property of the AbortController interface returns an AbortSignal object instance, which can be used to communicate with/abort an asynchronous operation as desired.
Inherited from
AbortController.signal
spawned
spawned:
boolean=false
Defined in: packages/core/src/methods/abortVar.ts:19
Methods
abort()
abort(
reason?):void
Defined in: packages/core/src/methods/abortVar.ts:23
The abort() method of the AbortController interface aborts an asynchronous operation before it has completed.
Parameters
reason?
any
Returns
void
Overrides
AbortController.abort
Variable<T, Params>
Defined in: packages/core/src/methods/variable.ts:27
Interface for context variables in Reatom
Variables maintain values within the context of a computation tree, allowing for context-aware state similar to React’s Context API but with more granular control and integration with Reatom’s reactive system.
See
https://github.com/tc39/proposal-async-context?tab=readme-ov-file#asynccontextvariable
Extended by
Type Parameters
T
T extends NonUndefined
Type of the stored value
Params
Params extends any[] = any[]
Constructors
Constructor
new Variable<
T,Params>(options?):Variable<T,Params>
Defined in: packages/core/src/methods/variable.ts:34
Parameters
options?
AsyncVariableOptions<T, Params>
Returns
Variable<T, Params>
Properties
_findReactiveStartIndex
protected_findReactiveStartIndex:number=0
Defined in: packages/core/src/methods/variable.ts:28
create()
protectedcreate: (…params) =>T
Defined in: packages/core/src/methods/variable.ts:30
Parameters
params
…Params
Returns
T
name
readonlyname:`var#${string}`
Defined in: packages/core/src/methods/variable.ts:32
run
run:
GenericAction<<Params,Payload>(value,cb, …params) =>Payload>
Defined in: packages/core/src/methods/variable.ts:97
Executes a callback function with the variable set to a specific value within that execution context
This method creates a new frame in the context tree where the variable is
bound to the provided value. The callback function runs within this frame,
allowing any code inside (and its descendants) to access this value via
get().
Example
const userVar = variable<string>('user')
userVar.run('Alice', () => { console.log(userVar.get()) // 'Alice' })
// Passing parameters to callback const result = userVar.run('Bob', (x, y) => x + y, 2, 3) console.log(result) // 5Template
Types of parameters passed to the callback
Template
Return type of the callback
Param
The value to set for this variable during callback execution. Cannot be undefined.
Param
The callback function to execute with the variable set
Param
Additional parameters to pass to the callback
Returns
The return value of the callback
Throws
If value is undefined
spawn
spawn:
GenericAction<<Params,Payload>(cb, …params) =>Payload>
Defined in: packages/core/src/methods/variable.ts:122
This utility allow you to start a function which will NOT follow the async context of this variable.
Example
// If you want to start a fetch when the atom gets a subscription, // but don't want to abort the fetch when the subscription is lost to save the data anyway. const some = atom('...').extend( withConnectHook((target) => { abortVar.spawn(async () => { // here `wrap` doesn't follow the connection abort const data = await wrap(api.getSome()) some(data) }) }), )Methods
find()
find<
Result>(cb?,frame?):undefined|Result
Defined in: packages/core/src/methods/variable.ts:165
Traverses the frame tree to find and map the variable value.
Type Parameters
Result
Result = T
Return type of the callback
Parameters
cb?
(payload) => undefined | Result
Optional transformation callback
frame?
Frame<any, any[], any> = ...
Optional frame to check (defaults to current top frame)
Returns
undefined | Result
The transformed value or undefined if not found
first()
first(
frame):undefined|T
Defined in: packages/core/src/methods/variable.ts:139
Gets the variable value from the first frame only, without traversing the whole frame tree
Unlike get() which searches through parent frames, this method only
checks the top frame. Returns undefined if the variable is not set in the
frame.
Parameters
frame
Frame<any, any[], any> = ...
Returns
undefined | T
The value in the frame, or undefined if not set
get()
get(
frame?):undefined|T
Defined in: packages/core/src/methods/variable.ts:63
Gets the passed frame value of the variable
Parameters
frame?
Frame<any, any[], any>
Optional frame to check (defaults to current top frame)
Returns
undefined | T
The current value
Throws
If the variable is not found in the frame tree
has()
has(
frame?):boolean
Defined in: packages/core/src/methods/variable.ts:150
Checks if the variable exists in the passed frame stack
Parameters
frame?
Frame<any, any[], any>
Optional frame to check (defaults to current top frame)
Returns
boolean
True if the variable exists in the context
set()
set(…
params):T
Defined in: packages/core/src/methods/variable.ts:195
Sets a new variable value for CURRENT frame. Be aware that it is mostly for internal use!
Parameters
params
…Params
Parameters passed to the setter function
Returns
T
The new value
Interfaces
AbortSubscription
Defined in: packages/core/src/methods/abortVar.ts:30
Properties
[asyncDispose]
[asyncDispose]:
Unsubscribe
Defined in: packages/core/src/methods/abortVar.ts:34
[dispose]
[dispose]:
Unsubscribe
Defined in: packages/core/src/methods/abortVar.ts:33
controller
controller:
ReatomAbortController
Defined in: packages/core/src/methods/abortVar.ts:31
unsubscribe
unsubscribe:
Unsubscribe
Defined in: packages/core/src/methods/abortVar.ts:32
AsyncVariableOptions<T, Params>
Defined in: packages/core/src/methods/variable.ts:8
Type Parameters
T
T extends NonUndefined
Params
Params extends any[] = any[]
Properties
create()?
optionalcreate: (…params) =>T
Defined in: packages/core/src/methods/variable.ts:14
Parameters
params
…Params
Returns
T
defaultValue?
optionaldefaultValue:T
Defined in: packages/core/src/methods/variable.ts:13
name?
optionalname:string
Defined in: packages/core/src/methods/variable.ts:12
Effect()<State>
Defined in: packages/core/src/methods/effect.ts:10
Derived state container.
A computed atom automatically tracks dependencies and recalculates only when those dependencies change. The calculation is performed lazily, only when the computed value is read AND subscribed to.
Extends
Computed<State>
Type Parameters
State
State
The type of derived state
Effect(…
params):State
Defined in: packages/core/src/methods/effect.ts:10
Derived state container.
A computed atom automatically tracks dependencies and recalculates only when those dependencies change. The calculation is performed lazily, only when the computed value is read AND subscribed to.
Parameters
params
…[]
Parameters to pass to the atom
Returns
State
The atom’s payload (typically its current state)
Properties
__reatom
__reatom:
AtomMeta
Defined in: packages/core/src/core/atom.ts:106
Reference to the atom’s internal metadata.
Inherited from
actions
Defined in: packages/core/src/core/atom.ts:86
Bind methods to the atom to extend its functionality.
Deprecated
Use extend instead
Inherited from
extend
Defined in: packages/core/src/core/atom.ts:92
Extension system to add capabilities to atoms. Allows adding middleware, methods, or other functionality to modify atom behavior.
Inherited from
set
set:
unknown
Defined in: packages/core/src/core/atom.ts:79
Inherited from
subscribe()
subscribe: (
cb?) =>Unsubscribe
Defined in: packages/core/src/core/atom.ts:103
Subscribe to state changes, with the first call happening immediately. When a subscriber is added, the callback is immediately invoked with the current state. After that, it’s called whenever the atom’s state changes.
Parameters
cb?
(state) => any
Callback function that receives the atom’s state when it changes
Returns
An unsubscribe function that removes the subscription when called
Inherited from
unsubscribe
unsubscribe:
Unsubscribe
Defined in: packages/core/src/methods/effect.ts:11
Type Aliases
Deatomize<T>
Deatomize<
T> =TextendsLinkedListLikeAtom<infer T> ?TextendsLinkedList<LLNode<infer T>> ?Deatomize<T>[] :never:TextendsAtomLike<infer T, infer Params, infer Payload> ?TextendsAtomLike<ActionState<Params,Payload>,Params,Payload> ?T:Deatomize<T> :TextendsMap<infer K, infer T> ?Map<K,Deatomize<T>> :TextendsSet<infer T> ?Set<Deatomize<T>> :Textends infer T[] ?Deatomize<T>[] :TextendsPrimitive|Builtin?T:TextendsRecord<PropertyKey,unknown> ?{ [K in keyof T]: Deatomize<T[K]> }:T
Defined in: packages/core/src/methods/deatomize.ts:27
Type utility that recursively unwraps atom types to their state types
This complex type recursively traverses a type structure, unwrapping atoms to their contained state types. It handles various container types like arrays, maps, sets, and objects.
Type Parameters
T
T
The type to unwrap
Returns
Unwrapped version of the type with atoms replaced by their state types
FunctionSource
FunctionSource =
string
Defined in: packages/core/src/methods/memo.ts:33
Type representing the source of a function as a string. Used for caching and identification purposes.
Variables
abortVar
abortVar:
AbortVariable
Defined in: packages/core/src/methods/abortVar.ts:209
Global abort variable that precess AbortController’s coupled to the current frame stack.
The abortVar is computed from all other abort atoms in the current frame tree, which allows for propagation of abortion signals through the computation hierarchy. This is a critical component for cancellation handling in Reatom’s async operations.
Examples
// Trigger abortion of the current frame abortVar.abortCurrent('Operation cancelled')// Trigger abortion of the current frame stack abortVar.get()?.abort('Operation cancelled')// Check if current operation (the whole frame stack) is aborted abortVar.throwIfAborted() // continue operation...// Get AbortController for fetch API const { controller, unsubscribe } = abortVar.subscribe() await fetch('/api/data', { signal: controller.signal }) unsubscribe()log
log:
Action<any[],any>
Defined in: packages/core/src/methods/connectLogger.ts:74
A special logging action for debugging Reatom applications.
log provides an enhanced logging experience with automatic tracing and
production-safe output. It forwards all arguments to the native console.log
while providing additional context about the call stack and dependencies.
Key Benefits
- Short and handy name - Easy to type and use throughout your codebase
- Automatic stack tracing - Shows the relative call stack each time it’s called
- Use it everywhere - Logs are only visible when
connectLogger()is active - Production-safe - Logs won’t appear in production builds when logger is not connected
- Context-aware - Integrates with Reatom’s dependency tracking system
- Extendable - You can extend it with other extensions to add custom behavior
Examples
import { log } from '@reatom/core'
// Make LOG available globally (recommended) declare global { var LOG: typeof log } globalThis.LOG = log
// Use anywhere in your code const myAtom = atom((ctx) => { const value = ctx.spy(someAtom) LOG('Current value:', value) return value * 2 })// In actions const myAction = action((ctx, payload) => { LOG('Action called with:', payload) // ... action logic })// Multiple arguments like console.log LOG('Debug info:', { foo: 'bar' }, [1, 2, 3])// Extend LOG with custom behavior using withCallHook import { withCallHook } from '@reatom/core'
LOG.extend( withCallHook((ctx, params) => { // Send logs to a remote service sendToAnalytics({ level: 'debug', args: params }) }), )See
connectLogger - Must be called to enable logging output
parseAtoms()
parseAtoms: <
Value>(value) =>Deatomize<Value> =deatomize
Defined in: packages/core/src/methods/deatomize.ts:113
Recursively unwraps atoms in a value to get their current states
This function deeply traverses a value, including nested objects, arrays, maps, and sets, replacing atoms with their current state values. It’s useful for serialization, debugging, or creating snapshots of state that don’t contain reactive references.
Type Parameters
Value
Value
The type of value to parse
Parameters
value
Value
The value containing atoms to unwrap
Returns
Deatomize<Value>
A new value with all atoms replaced by their current states
Example
const user = { id: 42, name: atom('John', 'userName'), stats: { score: atom(100, 'userScore'), badges: atom(['gold', 'silver'], 'userBadges'), }, }
// Results in: { id: 42, name: 'John', stats: { score: 100, badges: ['gold', 'silver'] }} const plainUser = deatomize(user)Deprecated
Use deatomize instead
reatomObservable()
constreatomObservable: {<T>(producer,init?,name?):Atom<undefined|T>; <T>(producer,init,name?):Atom<T>; }
Defined in: packages/core/src/methods/reatomObservable.ts:133
Creates a Reatom atom from an observable-like data source.
This function bridges external observable sources (like RxJS observables, event emitters, or custom observable implementations) with Reatom’s reactive system. The atom will automatically subscribe to the observable when it gains subscribers and unsubscribe when it loses all subscribers.
Call Signature
<
T>(producer,init?,name?):Atom<undefined|T>
Type Parameters
T
T
Parameters
producer
Producer<T>
init?
undefined
name?
string
Returns
Atom<undefined | T>
Call Signature
<
T>(producer,init,name?):Atom<T>
Type Parameters
T
T
Parameters
producer
Producer<T>
init
T | () => T
name?
string
Returns
Atom<T>
Examples
// With RxJS Observable import { interval } from 'rxjs' const timerAtom = reatomObservable(interval(1000))// With custom observable function const customAtom = reatomObservable((setter) => { const id = setInterval(() => setter(Date.now()), 1000) return () => clearInterval(id) })// With MobX observable import { autorun, observable } from 'mobx' const mobxStore = observable({ count: 0 }) const atomWithDefault = reatomObservable( () => autorun(() => mobxStore.count), () => mobxStore.count, )// With addEventListener const clickAtom = reatomObservable((setter) => { document.addEventListener('click', setter) return () => document.removeEventListener('click', setter) })Template
The type of values emitted by the observable
Param
Either a function that accepts a setter callback and returns an unsubscribe function, or an object with a subscribe method
Param
Optional initial value or function that returns the initial
value. If not provided, the atom starts with undefined
Returns
A Reatom atom that reflects the observable’s values
retryComputed()
constretryComputed: {(target):never; <T>(target):T; }
Defined in: packages/core/src/methods/retry.ts:38
Retries computed atom by resetting its dependencies and re-evaluating the computed function .
Call Signature
(
target):never
Parameters
target
Returns
never
Call Signature
<
T>(target):T
Type Parameters
T
T
Parameters
target
AtomLike<any, any, T>
Returns
T
Template
The return type of the atom.
Param
The atom to retry.
Returns
The result of the atom after retrying.
Throws
If the target is not an action.
rollback
rollback:
Action<[any],void>
Defined in: packages/core/src/methods/transaction.ts:107
select()
select: <
State>(cb,equal,key?) =>State=memo
Defined in: packages/core/src/methods/memo.ts:162
Memoize additional computation inside a different calls of an atom (computed or an effect) or an action.
It’s useful when you want to avoid recomputing of the whole computed function, especially if the computation is expensive. You could create an external atom by yourself, but it is not handy sometimes.
The memo function takes a callback function cb that returns the value to
be memoized, an optional equal function that compares the new and old
values to determine if the memoized value should be updated, and an optional
key to uniquely identify the memoized value.
Important note: The created internal atom only uses the first passed callback function. This means it’s unsafe to rely on data from the closure that changes on every recall, as subsequent calls will not update the callback used by the internal atom.
Note for rare cases: A created underhood atom is memorized for each memo by
the passed function sources from “toString()” method, so every computed
callback in different memos of the same atom should contain different code.
However, you can provide a custom key parameter to uniquely identify
different memo calls instead of relying on toString().
When a custom key is provided, the toString() duplication check is
bypassed, allowing you to use the same callback function multiple times
within the same atom by providing different keys for each usage.
Type Parameters
State
State
Parameters
cb
A function that returns the value to be selected and memoized.
() => State | (state?) => State
equal
(newState, oldState) => boolean
key?
string
An optional unique identifier for the memoized value. Defaults to
cb.toString(). Used to distinguish between different memo calls within
the same computed function. Providing a custom key is recommended when
using similar callback functions to avoid conflicts.
Returns
State
The memoized value.
Examples
// This is very useful to memoize not just the end string, // but, for example, a template computation inside `reatomComponent` or so on. export const listSum = computed(() => { // Simple call of `list().length` will cause extra recomputations for elements sorting or its internal changes. // correct optimal way, the component will rerender only on `length` change const length = memo(() => list().length) // you could call different `memo` many times in one computed const sum = memo(() => list().reduce((acc, el) => acc + el().value, 0))
return `The sum of ${length} elements is: ${sum}` }, 'listSum')// An example of using the equality function as part of the logic const scroll = atom(0, 'scroll') const throttledScroll = computed(() => { const { state } = memo( () => ({ state: scroll(), time: Date.now() }), // Only update if 50ms have passed since the last update (next, prev) => prev.time + 50 < Date.now(), ) return state }, 'throttledScroll')// Using memo in actions for expensive computations const processData = action((data: string[]) => { // You can even create a service, but not one that is tied only to this action. const myService = memo(() => new Service())
myService.send(data) }, 'processData')Deprecated
Use memo instead
spawn
spawn:
AbortVariable["spawn"]
Defined in: packages/core/src/methods/abortVar.ts:212
Deprecated
Use abortVar.spawn instead
transactionVar
transactionVar:
TransactionVariable
Defined in: packages/core/src/methods/transaction.ts:105
variable()
variable: {<
T>(name?):Variable<T, [T]>; <Params,Payload>(set,name?):Variable<Payload,Params>; }
Defined in: packages/core/src/methods/variable.ts:235
Creates a new context variable with getter and setter functionality
This implementation provides a similar capability to the proposed TC39 AsyncContextVariable, allowing you to maintain values that are specific to a particular execution context. Variables created with this function can be accessed and modified within their frame context.
Call Signature
<
T>(name?):Variable<T, [T]>
Type Parameters
T
T extends NonUndefined
Parameters
name?
string
Returns
Variable<T, [T]>
Call Signature
<
Params,Payload>(set,name?):Variable<Payload,Params>
Type Parameters
Params
Params extends any[]
Payload
Payload extends NonUndefined
Parameters
set
(…params) => Payload
name?
string
Returns
Variable<Payload, Params>
Example
// Simple variable with string values const currentUser = variable<string>('currentUser')
// Set the value currentUser.set('Alice')
// Get the value console.log(currentUser.get()) // 'Alice'
// Run code with a different value currentUser.run('Bob', () => { console.log(currentUser.get()) // 'Bob' })
// Advanced variable with custom setter logic const userRole = variable((role: string, permissions: string[]) => { return { role, permissions } }, 'userRole')
userRole.set('admin', ['read', 'write', 'delete'])Template
The type of the simple variable (when used with just a name)
Template
Types of parameters for the setter function
Template
The type of the stored value
See
https://github.com/tc39/proposal-async-context?tab=readme-ov-file#asynccontextvariable
withRollback()
withRollback: () =>
GenericExt
Defined in: packages/core/src/methods/transaction.ts:106
Extension to follow rollback context. For atoms it adds prev state
restoration when relative rollback() appears. For actions it adds error
handling and call rollback() automatically.
Returns
wrap()
wrap: {<
Params,Payload>(target,frame?): (…params) =>Payload; <T>(target,frame?):Promise<Awaited<T>>; }
Defined in: packages/core/src/methods/wrap.ts:47
Preserves Reatom’s reactive context across async boundaries or function calls.
This is a CRITICAL function in Reatom that ensures proper context tracking across asynchronous operations like Promises, setTimeout, event handlers, and more. Without proper wrapping, atoms would lose their context after async operations, leading to “Missed context” errors when attempting to update state.
Wrap handles two scenarios:
- Function wrapping: Returns a new function that preserves context when called
- Promise wrapping: Returns a new promise that preserves context through its chain
Call Signature
<
Params,Payload>(target,frame?): (…params) =>Payload
Type Parameters
Params
Params extends any[]
Payload
Payload
Parameters
target
(…params) => Payload
frame?
Frame<any, any[], any>
Returns
(…
params):Payload
Parameters
params
…Params
Returns
Payload
Call Signature
<
T>(target,frame?):Promise<Awaited<T>>
Type Parameters
T
T
Parameters
target
T
frame?
Frame<any, any[], any>
Returns
Promise<Awaited<T>>
Example
// Wrapping a function (e.g., an event handler) button.addEventListener( 'click', wrap(() => { counter((prev) => prev + 1) // Works, context preserved }), )
// Wrapping async operations action(async () => { const response = await wrap(fetch('/api/data')) const data = await wrap(response.json()) results(data) // Works, context preserved })Template
The parameter types when wrapping a function
Template
The return type when wrapping a function
Template
The promise type when wrapping a promise
Param
The function or promise to wrap with context preservation
Param
The frame to use (defaults to the current top frame)
Returns
A wrapped function or promise that preserves reactive context
See
https://github.com/tc39/proposal-async-context?tab=readme-ov-file#asynccontextsnapshotwrap
Functions
connectLogger()
connectLogger():
void
Defined in: packages/core/src/methods/connectLogger.ts:104
Sets up and connects a logger to the Reatom system for debugging and tracing.
This function enhances all non-private atoms and actions with logging capabilities. When an atom’s value changes or an action is called, it logs the event with relevant information to the console including:
- Previous and current state for atoms
- Parameters and return values for actions
- Complete dependency stack traces
- Error information when exceptions occur
The logger adapts to the environment, using different formatting for browser and Node.js. Private atoms (those with names starting with '' or containing ’.’) are not logged.
Returns
void
Example
// Connect the logger at application startup import { connectLogger } from '@reatom/core'
connectLogger()deatomize()
deatomize<
Value>(value):Deatomize<Value>
Defined in: packages/core/src/methods/deatomize.ts:76
Recursively unwraps atoms in a value to get their current states
This function deeply traverses a value, including nested objects, arrays, maps, and sets, replacing atoms with their current state values. It’s useful for serialization, debugging, or creating snapshots of state that don’t contain reactive references.
Type Parameters
Value
Value
The type of value to parse
Parameters
value
Value
The value containing atoms to unwrap
Returns
Deatomize<Value>
A new value with all atoms replaced by their current states
Example
const user = { id: 42, name: atom('John', 'userName'), stats: { score: atom(100, 'userScore'), badges: atom(['gold', 'silver'], 'userBadges'), }, }
// Results in: { id: 42, name: 'John', stats: { score: 100, badges: ['gold', 'silver'] }} const plainUser = deatomize(user)effect()
effect<
T>(cb,name?):Computed<T> &AbortExt&DynamicSubscriptionExt&object
Defined in: packages/core/src/methods/effect.ts:56
Creates a reactive side effect that automatically tracks dependencies and cleans itself up.
effect is similar to computed but designed for running side effects. It
automatically subscribes to any atoms read within the callback (cb). When
the effect’s reactive context is aborted (e.g., component unmount in
reatomFactoryComponent, cancellation in withAbort / withAsyncData), the
effect’s execution is stopped, and any ongoing async operations within it
(like await wrap(sleep(...))) are cancelled.
Type Parameters
T
T
Parameters
cb
() => T
The function to run as a side effect. It can be async. Any atoms
read inside cb will become dependencies.
name?
string
Optional name for debugging purposes. Auto-generated if not provided.
Returns
Computed<T> & AbortExt & DynamicSubscriptionExt & object
The new computed atom with unsubscribe method to manually clean up
the effect. Calling this function is usually not necessary when effect is
used within managed contexts like reatomFactoryComponent or
withConnectHook, as cleanup happens automatically.
Example
import { atom, effect, wrap, sleep, isAbort } from '@reatom/core'
const isActive = atom(true, 'isActive') const data = atom(0, 'data')
// This effect polls data every 5 seconds while isActive is true const polling = effect(async () => { if (!isActive()) return // Depends on isActive
console.log('Polling started...') while (true) { const fetchedData = await wrap(fetch('/api/poll')) const jsonData = await wrap(fetchedData.json()) data(jsonData.value) await wrap(sleep(5000)) // Abortable sleep == debounce } }, 'pollingEffect')
// To manually stop: // polling.unsubscribe()framePromise()
framePromise(
queue):Promise<unknown>
Defined in: packages/core/src/methods/framePromise.ts:79
Request the result of the current atom or action function as a promise.
Returns a promise that resolves to the current execution frame’s state
(action payload or atom state). Use it to catch errors from subsequent
operations in a cleaner way than traditional try-catch. Use finally to
clean up resources and so on. This method respects wrap and abortVar
policies.
Inspired by TC39 explicit resource management proposal, but simpler and coupled to Reatom’s async stack for an ergonomic usage.
Parameters
queue
QueueKind = 'effect'
Queue type to schedule in (default: “effect”)
Returns
Promise<unknown>
Promise that resolves with the current frame’s state
Examples
export const processPayment = action(async (orderId: string) => { framePromise().catch((error) => showErrorNotification(error))
let order = await wrap(fetchOrder(orderId)) await wrap(validateInventory(order)) await wrap(chargeCustomer(order)) await wrap(updateOrderStatus(order, 'completed'))
return order })// Classic approach - boilerplate with try-catch export const doSome = action(async () => { try { await wrap(fetchUser()) await wrap(updateProfile()) await wrap(syncData()) } catch (error) { toast(error) } })
// native using - no try-catch and no "finally" logic // only resource management with extra variables // you can adapt `toast`, but without the payload / error data export const doSome = action(async () => { using _ = toast await wrap(fetchUser()) await wrap(updateProfile()) await wrap(syncData()) })
// With our framePromise() - clean and declarative export const doSome = action(async () => { framePromise().catch((error) => toast(error)) await wrap(fetchUser()) await wrap(updateProfile()) await wrap(syncData()) })// Native using works only within the current function scope=* export const processOrder = action(async (orderId: string) => { withErrorLogging() // Impossible with native using await wrap(fetchOrder(orderId)) })
// But framePromise works with the current action/atom frame! // Helper functions can use parent's framePromise - powerful composition! let withErrorLogging = () => { framePromise().catch((error) => logger.error(error)) } export const processOrder = action(async (orderId: string) => { withErrorLogging() // Helper uses the SAME action frame! await wrap(fetchOrder(orderId)) })See
https://github.com/tc39/proposal-explicit-resource-management
getCalls()
getCalls<
Params,Payload>(target):object[]
Defined in: packages/core/src/methods/ifChanged.ts:97
Retrieves new action calls that occurred in the current batch.
This utility function tracks action invocations and returns an array of new calls that have been made during the current batch. It’s particularly useful for monitoring action activity within computed atoms or effects without triggering side effects during the action execution itself.
In a computed atom, the function compares the current action state with the previous frame’s state to determine which calls are new. If this is the first time the action is being tracked, all current calls are considered new. Otherwise, only calls that weren’t present in the previous frame are returned. If the computed triggered by some other dependent atom change, the function may return an empty array. The past calls are not stored!
Type Parameters
Params
Params extends any[]
Array type representing the action’s parameter types
Payload
Payload
Type of the action’s return value/payload
Parameters
target
Action<Params, Payload>
The action to monitor for new calls
Returns
object[]
Array of new action calls, each containing the action’s payload (return value) and the parameters it was called with
Example
// Monitor API calls in an effect const apiCall = action((endpoint: string) => fetch(endpoint), 'apiCall')
effect(() => { const newCalls = getCalls(apiCall) newCalls.forEach(({ payload, params }) => { console.log(`API called: ${params[0]}, Response:`, payload) }) }, 'apiMonitor')Throws
If target is a reactive atom instead of an action
getSerial()
getSerial(
frame):string
Defined in: packages/core/src/methods/getStackTrace.ts:10
Parameters
frame
Frame<any, any[], any> = ...
Returns
string
ifCalled()
ifCalled<
Params,Payload>(target,cb):void
Defined in: packages/core/src/methods/ifChanged.ts:140
Type Parameters
Params
Params extends any[]
Payload
Payload
Parameters
target
Action<Params, Payload>
cb
(payload, params) => void
Returns
void
Deprecated
Use getCalls instead
ifChanged()
ifChanged<
T>(target,cb):void
Defined in: packages/core/src/methods/ifChanged.ts:40
Executes a callback when an atom’s state changes
This utility evaluates if an atom’s state has changed during the current frame execution and calls the provided callback with the new state (and optionally the previous state if available).
Type Parameters
T
T extends AtomLike<any, any[], any>
Type extending AtomLike
Parameters
target
T
The atom to monitor for changes
cb
(newState, oldState?) => void
Callback to execute when the atom changes
Returns
void
Example
// Log when the user's name changes ifChanged(userName, (newName, oldName) => { console.log(`Name changed from ${oldName} to ${newName}`) })Throws
If target is not a reactive atom
isCausedBy()
isCausedBy(
target,frame?,visited?):boolean
Defined in: packages/core/src/methods/isCausedBy.ts:25
Determines if an atom is part of the causal chain leading to the current computation
This recursive function checks if the given atom has caused the current computation by traversing the computation tree. It’s useful for determining dependencies and understanding the flow of state changes through your application.
Parameters
target
The atom to check if it’s part of the causal chain
frame?
Frame<any, any[], any> = ...
The frame to check (defaults to the current
top frame). Default is top()
visited?
Set<Frame<any, any[], any>> = ...
Returns
boolean
True if the target atom is part of the causal chain, false otherwise
Example
// Check if user atom changes caused the current computation if (isCausedBy(userAtom)) { console.log('This computation was triggered by user state change') }isChanged()
isChanged(
target):boolean
Defined in: packages/core/src/methods/ifChanged.ts:7
Parameters
target
Returns
boolean
isSkip()
isSkip(
target):boolean
Defined in: packages/core/src/methods/getStackTrace.ts:4
Parameters
target
Returns
boolean
memo()
memo<
State>(cb,equal,key?):State
Defined in: packages/core/src/methods/memo.ts:112
Memoize additional computation inside a different calls of an atom (computed or an effect) or an action.
It’s useful when you want to avoid recomputing of the whole computed function, especially if the computation is expensive. You could create an external atom by yourself, but it is not handy sometimes.
The memo function takes a callback function cb that returns the value to
be memoized, an optional equal function that compares the new and old
values to determine if the memoized value should be updated, and an optional
key to uniquely identify the memoized value.
Important note: The created internal atom only uses the first passed callback function. This means it’s unsafe to rely on data from the closure that changes on every recall, as subsequent calls will not update the callback used by the internal atom.
Note for rare cases: A created underhood atom is memorized for each memo by
the passed function sources from “toString()” method, so every computed
callback in different memos of the same atom should contain different code.
However, you can provide a custom key parameter to uniquely identify
different memo calls instead of relying on toString().
When a custom key is provided, the toString() duplication check is
bypassed, allowing you to use the same callback function multiple times
within the same atom by providing different keys for each usage.
Type Parameters
State
State
Parameters
cb
A function that returns the value to be selected and memoized.
() => State | (state?) => State
equal
(newState, oldState) => boolean
key?
string
An optional unique identifier for the memoized value. Defaults to
cb.toString(). Used to distinguish between different memo calls within
the same computed function. Providing a custom key is recommended when
using similar callback functions to avoid conflicts.
Returns
State
The memoized value.
Examples
// This is very useful to memoize not just the end string, // but, for example, a template computation inside `reatomComponent` or so on. export const listSum = computed(() => { // Simple call of `list().length` will cause extra recomputations for elements sorting or its internal changes. // correct optimal way, the component will rerender only on `length` change const length = memo(() => list().length) // you could call different `memo` many times in one computed const sum = memo(() => list().reduce((acc, el) => acc + el().value, 0))
return `The sum of ${length} elements is: ${sum}` }, 'listSum')// An example of using the equality function as part of the logic const scroll = atom(0, 'scroll') const throttledScroll = computed(() => { const { state } = memo( () => ({ state: scroll(), time: Date.now() }), // Only update if 50ms have passed since the last update (next, prev) => prev.time + 50 < Date.now(), ) return state }, 'throttledScroll')// Using memo in actions for expensive computations const processData = action((data: string[]) => { // You can even create a service, but not one that is tied only to this action. const myService = memo(() => new Service())
myService.send(data) }, 'processData')memoKey()
memoKey<
T>(key,create):T
Defined in: packages/core/src/methods/memo.ts:19
Internal utility for keyed memoization within an atom’s execution context.
Caches values by key within the current atom frame, creating the value on first access and returning the cached value on subsequent calls. This enables persistent memoization across multiple invocations of the same atom.
The cache is scoped per-atom and persists across all calls to that atom within the same context, making it suitable for creating internal computed atoms or other resources that should be created once and reused.
Type Parameters
T
T
The type of value being cached
Parameters
key
string
Unique identifier for the cached value within the atom
create
() => T
Factory function to create the value if not already cached
Returns
T
The cached value, either newly created or retrieved from cache
peek()
peek<
Params,Result>(cb, …params):Result
Defined in: packages/core/src/methods/peek.ts:38
Executes a callback in the current context without reactive bindings (dependencies tracking)
Type Parameters
Params
Params extends any[]
Result
Result
Parameters
cb
(…params) => Result
params
…Params
Returns
Result
Examples
// reset paging on search changes effect(() => { const searchState = search()
// get page state without subscribing to it! if (peek(page) > 1) peek(0) })const query = atom('', 'query') const someResource = computed( async () => api.getSome(query()), 'someResource', ).extend(withAsyncData())
const tip = computed(() => { if (!someResource.ready()) { return 'Searching...' }
const list = someResource.data()
if (list.length === 0) { // no need to subscribe to the query changes! return peek(query) ? 'Nothing found' : 'Try to search something' }
return `Found ${list.length} elements` })reatomTransaction()
reatomTransaction():
TransactionVariable
Defined in: packages/core/src/methods/transaction.ts:37
Creates a transaction variable with rollback capabilities. This variable stores a list of rollback functions that can be executed to revert state changes made within a transaction.
Returns
TransactionVariable
A transaction variable with withRollback middleware and a
rollback action.
reset()
reset<
T>(target):void
Defined in: packages/core/src/methods/retry.ts:16
Removes all computed atom dependencies. Useful for resources / effects invalidation.
Note that this method not recall and recompute the atom, it only throws it’s
deps. Use retryComputed to reevaluate the computed.
Type Parameters
T
T extends AtomLike<any, any[], any>
Parameters
target
T
The reactive atom whose dependencies should be reset.
Returns
void
Throws
If the target is an action.
schedule()
schedule<
T>(fn,queue):Promise<T>
Defined in: packages/core/src/methods/schedule.ts:15
Schedule a callback to execute after all current computations complete.
The callback is added to the specified queue (“effect” by default) and processes alongside subscription callbacks and other side effects. This method respects wrap and abortVar policies.
Type Parameters
T
T
Parameters
fn
() => T
Callback function to execute
queue
QueueKind = 'effect'
Queue type to schedule in (default: “effect”)
Returns
Promise<T>
Promise that resolves with the callback’s return value
take()
Call Signature
take<
Return>(target,name?):Promise<Awaited<Return>>
Defined in: packages/core/src/methods/take.ts:42
Awaits the next update of an atom or call of an action.
This function returns a Promise that resolves when the specified atom’s state changes or when the specified action is called. This is valuable for orchestrating workflows that depend on future state changes or action calls.
Note: Must be used with wrap() when used in an async context to preserve
reactive context.
Type Parameters
Return
Return
Parameters
target
The atom or action to wait for
AtomLike<any, any, Return> | () => Return
name?
string
Optional name for debugging purposes
Returns
Promise<Awaited<Return>>
A promise that resolves with the next value of the atom or action result
Example
// Wait for form validation before proceeding const submitWhenValid = action(async () => { while (true) { const currentData = formData() const error = validate(currentData) if (!error) break // Exit loop if valid
formData({ ...currentData, error }) // Show error
// Wait for the next change in formData - need wrap() to preserve context await wrap(take(formData)) } // Now formData is valid, proceed with submission... })Call Signature
take<
Return,Result>(target,map,name?):Result|Promise<Result>
Defined in: packages/core/src/methods/take.ts:58
Awaits the next update of the target AtomLike and maps the result. If the map function executes synchronously without throwing, its result is returned directly. Otherwise, a promise is returned.
Type Parameters
Return
Return
The type of the awaited value from the target.
Result
Result
The type of the mapped result.
Parameters
target
The AtomLike to await.
AtomLike<any, any, Return> | () => Return
map
(value) => Result
A function to map the awaited value.
name?
string
Optional name for debugging.
Returns
Result | Promise<Result>
The mapped result or a promise that resolves with the mapped result.
withObservable()
withObservable<
Target>(producer,init?):Ext<Target>
Defined in: packages/core/src/methods/reatomObservable.ts:71
Extends an existing atom to synchronize with an observable-like data source.
This extension bridges external observable sources (like RxJS observables, event emitters, or custom observable implementations) with Reatom’s reactive system. The extended atom will automatically subscribe to the observable when it gains subscribers and unsubscribe when it loses all subscribers.
Type Parameters
Target
Target extends Atom<any, [any]>
The type of the atom being extended
Parameters
producer
Producer<AtomState<Target>>
Either a function that accepts a setter callback and returns an unsubscribe function, or an object with a subscribe method (like RxJS observables)
init?
() => AtomState<Target>
Optional initialization function that returns the initial value. This will be called when the atom is first connected
Returns
Ext<Target>
An extension function that adds observable synchronization to an atom
Examples
// Extending an existing atom with RxJS Observable import { interval } from 'rxjs' const counterAtom = atom(0) const timerAtom = counterAtom.extend(withObservable(interval(1000)))// With custom observable function const stateAtom = atom({ timestamp: 0 }) const liveAtom = stateAtom.extend( withObservable((setter) => { const id = setInterval(() => setter({ timestamp: Date.now() }), 1000) return () => clearInterval(id) }), )// With MobX observable, providing initial value import { autorun, observable } from 'mobx' const mobxStore = observable({ count: 0 }) const syncedAtom = atom(0).extend( withObservable((setter) => autorun(() => setter(mobxStore.count))), )// With DOM events const clickCountAtom = atom(0) const trackedAtom = clickCountAtom.extend( withObservable((setter) => { let count = 0 const handler = () => setter(++count) document.addEventListener('click', handler) return () => document.removeEventListener('click', handler) }), )