Documentation Index
Fetch the complete documentation index at: https://mintlify.com/tim-smart/effect-atom/llms.txt
Use this file to discover all available pages before exploring further.
The Registry module provides a container for managing atom state and subscriptions. It’s responsible for computing atom values, tracking dependencies, and notifying subscribers of changes.
Type definitions
Registry
interface Registry {
readonly [TypeId]: TypeId
readonly getNodes: () => ReadonlyMap<Atom.Atom<any> | string, Node<any>>
readonly get: <A>(atom: Atom.Atom<A>) => A
readonly mount: <A>(atom: Atom.Atom<A>) => () => void
readonly refresh: <A>(atom: Atom.Atom<A>) => void
readonly set: <R, W>(atom: Atom.Writable<R, W>, value: W) => void
readonly setSerializable: (key: string, encoded: unknown) => void
readonly modify: <R, W, A>(atom: Atom.Writable<R, W>, f: (_: R) => [returnValue: A, nextValue: W]) => A
readonly update: <R, W>(atom: Atom.Writable<R, W>, f: (_: R) => W) => void
readonly subscribe: <A>(atom: Atom.Atom<A>, f: (_: A) => void, options?: {
readonly immediate?: boolean
}) => () => void
readonly reset: () => void
readonly dispose: () => void
}
The registry manages atom state and provides methods for reading, writing, and subscribing to atoms.
Creation
make
Create a new Registry instance.
const make: (options?: {
readonly initialValues?: Iterable<readonly [Atom.Atom<any>, any]> | undefined
readonly scheduleTask?: ((f: () => void) => void) | undefined
readonly timeoutResolution?: number | undefined
readonly defaultIdleTTL?: number | undefined
}) => Registry
Initial values to hydrate atoms with
Custom task scheduler for batching updates. Defaults to immediate execution.
options.timeoutResolution
Resolution in milliseconds for idle TTL checks. Defaults to 1000.
Default idle TTL in milliseconds for all atoms. Atoms are disposed after this time if they have no subscribers.
Example
import { Registry } from "@effect-rx/rx"
const registry = Registry.make()
Example - With initial values
const registry = Registry.make({
initialValues: [
[userAtom, { id: 1, name: "Alice" }],
[themeAtom, "dark"]
]
})
Example - With React integration
import { startTransition } from "react"
const registry = Registry.make({
scheduleTask: (f) => startTransition(f)
})
Reading atoms
get
Get the current value of an atom.
registry.get<A>(atom: Atom.Atom<A>): A
Example
const count = registry.get(countAtom)
console.log(count) // 42
Reading an atom computes its value if it hasn’t been computed yet, and tracks it as a dependency of the current atom context (if any).
Writing atoms
set
Set the value of a writable atom.
registry.set<R, W>(atom: Atom.Writable<R, W>, value: W): void
Example
registry.set(countAtom, 42)
registry.set(userAtom, { id: 1, name: "Alice" })
update
Update an atom’s value based on its current value.
registry.update<R, W>(atom: Atom.Writable<R, W>, f: (_: R) => W): void
Function to compute new value from current value
Example
registry.update(countAtom, (n) => n + 1)
modify
Modify an atom and return a value.
registry.modify<R, W, A>(
atom: Atom.Writable<R, W>,
f: (_: R) => [returnValue: A, nextValue: W]
): A
Function that returns both a return value and the next atom value
Example
const previousCount = registry.modify(
countAtom,
(n) => [n, n + 1]
)
console.log(previousCount) // 42
console.log(registry.get(countAtom)) // 43
setSerializable
Set a serializable atom’s value using its serialization key.
registry.setSerializable(key: string, encoded: unknown): void
The serialization key of the atom
Example
// Hydrate from server data
const serverData = {
"user-preferences": { theme: "dark", locale: "en" }
}
for (const [key, value] of Object.entries(serverData)) {
registry.setSerializable(key, value)
}
Subscriptions
subscribe
Subscribe to changes in an atom’s value.
registry.subscribe<A>(
atom: Atom.Atom<A>,
f: (_: A) => void,
options?: { readonly immediate?: boolean }
): () => void
Callback function called when the value changes
If true, calls the callback immediately with the current value
Returns a cleanup function to unsubscribe.
Example
const unsubscribe = registry.subscribe(
countAtom,
(count) => console.log("Count:", count)
)
registry.set(countAtom, 42) // Logs: "Count: 42"
unsubscribe() // Stop listening
Example - Immediate callback
registry.subscribe(
countAtom,
(count) => console.log("Count:", count),
{ immediate: true }
)
// Immediately logs current value
mount
Mount an atom to keep it alive even without subscribers.
registry.mount<A>(atom: Atom.Atom<A>): () => void
Returns a cleanup function to unmount the atom.
Example
const unmount = registry.mount(backgroundTaskAtom)
// Atom stays active even with no subscribers
// ...
unmount() // Allow disposal
Lifecycle
refresh
Force an atom to recompute its value.
registry.refresh<A>(atom: Atom.Atom<A>): void
Example
// Manually refresh data
registry.refresh(userAtom)
reset
Reset the registry, clearing all atom state.
Example
// Clear all cached state
registry.reset()
This clears all atom values and resets them to their initial state. Subscribers remain active.
dispose
Dispose of the registry and all its atoms.
Example
// Clean up when done
registry.dispose()
After disposal, the registry cannot be used. Create a new registry if needed.
Debugging
getNodes
Get all active atom nodes for debugging.
registry.getNodes(): ReadonlyMap<Atom.Atom<any> | string, Node<any>>
Example
const nodes = registry.getNodes()
console.log("Active atoms:", nodes.size)
for (const [atom, node] of nodes) {
console.log("Atom:", atom)
console.log("Value:", node.value())
}
Effect integration
AtomRegistry
Effect Tag for accessing the current registry.
class AtomRegistry extends Context.Tag("@effect/atom/Registry/CurrentRegistry")<
AtomRegistry,
Registry
>() {}
Example
import { Effect } from "effect"
import { Registry } from "@effect-rx/rx"
const program = Effect.gen(function* () {
const registry = yield* Registry.AtomRegistry
const count = registry.get(countAtom)
return count
})
layer
Default Layer for providing a Registry.
const layer: Layer.Layer<AtomRegistry>
Example
import { Effect, Layer } from "effect"
const program = Effect.gen(function* () {
const registry = yield* Registry.AtomRegistry
return registry.get(countAtom)
})
const runnable = Effect.provide(program, Registry.layer)
layerOptions
Create a custom Layer with options.
const layerOptions: (options?: {
readonly initialValues?: Iterable<readonly [Atom.Atom<any>, any]> | undefined
readonly scheduleTask?: ((f: () => void) => void) | undefined
readonly timeoutResolution?: number | undefined
readonly defaultIdleTTL?: number | undefined
}) => Layer.Layer<AtomRegistry>
Example
const customLayer = Registry.layerOptions({
defaultIdleTTL: 60000, // 1 minute
timeoutResolution: 5000 // Check every 5 seconds
})
const program = Effect.provide(myProgram, customLayer)
Stream conversions
toStream
Convert an atom to a Stream of its values.
const toStream: {
<A>(atom: Atom.Atom<A>): (self: Registry) => Stream.Stream<A>
<A>(self: Registry, atom: Atom.Atom<A>): Stream.Stream<A>
}
Example
const countStream = Registry.toStream(registry, countAtom)
Stream.runForEach(countStream, (count) =>
Console.log(`Count: ${count}`)
)
toStreamResult
Convert a Result atom to a Stream that emits success values and fails on errors.
const toStreamResult: {
<A, E>(atom: Atom.Atom<Result.Result<A, E>>): (self: Registry) => Stream.Stream<A, E>
<A, E>(self: Registry, atom: Atom.Atom<Result.Result<A, E>>): Stream.Stream<A, E>
}
Example
const userStream = Registry.toStreamResult(registry, userAtom)
Stream.runForEach(userStream, (user) =>
Console.log(`User: ${user.name}`)
)
getResult
Get a Result atom’s value as an Effect.
const getResult: {
<A, E>(atom: Atom.Atom<Result.Result<A, E>>, options?: {
readonly suspendOnWaiting?: boolean | undefined
}): (self: Registry) => Effect.Effect<A, E>
<A, E>(self: Registry, atom: Atom.Atom<Result.Result<A, E>>, options?: {
readonly suspendOnWaiting?: boolean | undefined
}): Effect.Effect<A, E>
}
If true, the Effect suspends while the result is in a waiting state
Example
const getUserEffect = Registry.getResult(registry, userAtom)
const program = Effect.gen(function* () {
const user = yield* getUserEffect
console.log(user.name)
})
Type guards
isRegistry
Check if a value is a Registry.
const isRegistry: (u: unknown) => u is Registry
Example
if (Registry.isRegistry(value)) {
const count = value.get(countAtom)
}