← All reusables
reatomInstance
factoryInstallation
npx jsrepo add github/reatom/reusables reatomInstance Copy the source code below and save it to the specified file path in your project.
reatom-instance.ts
import {
abortVar,
computed,
reset,
withAbort,
withDisconnectHook,
} from '@reatom/core'
/**
* Wraps a computed that creates instances, managing their lifecycle
* automatically.
*
* - On connect: creates the instance via the `create` function.
* - On recompute: disposes the previous instance when a new one is created.
* - On disconnect: disposes the instance and resets the atom.
*
* This is useful for integrating imperative APIs (UI libraries, DOM nodes,
* class instances) with Reatom's reactive lifecycle.
*
* @example
* // Create a Web Audio oscillator that auto-disposes
* const oscillator = reatomInstance(
* () => audioContext.createOscillator(),
* (osc) => osc.stop(),
* )
*
* @param create - Factory function that creates the instance
* @param dispose - Cleanup function called on disconnect or when instance
* changes
* @param name - Optional debugging name for the computed atom
*/
export const reatomInstance = <I>(
create: () => I,
dispose?: (instance: I) => void,
name?: string,
) => {
const resource = computed(() => {
const instance = create()
abortVar.subscribe(() => dispose?.(instance))
return instance
}, name).extend(
withAbort(),
withDisconnectHook(() => {
resource.abort('disconnect')
reset(resource)
}),
)
return resource
} Documentation
reatomInstance
Lifecycle-managed factory for imperative instances. Creates objects lazily on subscribe and disposes them automatically when dependencies change or on abort.
reatomInstance(create, dispose?, name?)
Wraps a computed atom that calls create to produce an instance. The instance is:
- Created lazily — only when the atom gets a subscriber
- Disposed on recompute — when a reactive dependency changes, the previous instance is disposed before a new one is created
- Disposed on abort — calling
.abort()triggers the dispose callback - Reset on disconnect — when all subscribers leave, the atom resets so the next subscriber gets a fresh instance
Parameters
| Parameter | Type | Description |
|---|---|---|
create |
() => I |
Factory that creates the instance |
dispose |
(instance: I) => void |
Cleanup callback (optional) |
name |
string |
Debug name for the underlying computed atom (optional) |
Returns
A computed atom extended with withAbort() and withDisconnectHook().
Example
import { reatomInstance } from '#reatom/factory/reatom-instance'
// Manage a Web Audio oscillator
const oscillator = reatomInstance(
() => audioContext.createOscillator(),
(osc) => osc.stop(),
)
// Instance is created when subscribed
const unsub = oscillator.subscribe((osc) => {
osc.connect(audioContext.destination)
osc.start()
})
// Disposed and reset when unsubscribed
unsub()
Reactive dependencies
When the create function reads other atoms, the instance is automatically recreated (and the previous one disposed) when those atoms change:
import { atom } from '@reatom/core'
import { reatomInstance } from '#reatom/factory/reatom-instance'
const url = atom('/api/data')
const eventSource = reatomInstance(
() => new EventSource(url()),
(es) => es.close(),
)
// When `url` changes, the old EventSource is closed
// and a new one is created with the updated URL.
See also
- withInstance — Atom extension that adds a lifecycle-managed
.instanceproperty
Example
import { atom } from '@reatom/core'
import { reatomInstance } from './reatom-instance'
// --- Manage an imperative resource lifecycle ---
// Create a canvas rendering context that auto-disposes
const canvas = reatomInstance(
() => {
const el = document.createElement('canvas')
document.body.appendChild(el)
return el.getContext('2d')!
},
(ctx) => ctx.canvas.remove(),
'canvas',
)
// The context is created lazily on first subscribe
const unsub = canvas.subscribe((ctx) => {
ctx.fillStyle = 'steelblue'
ctx.fillRect(0, 0, 100, 100)
})
// Unsubscribing removes the canvas from the DOM
unsub()
// --- Reactive dependencies: instance recreated on change ---
const url = atom('wss://example.com/feed')
// When `url` changes, the old WebSocket is closed
// and a new one opens with the updated URL.
void reatomInstance(
() => new WebSocket(url()),
(ws) => ws.close(),
'socket',
)