← All reusables

withInstance

extension

Installation

npx jsrepo add github/reatom/reusables withInstance

Registry dependencies

Documentation

withInstance

Atom extension that adds a lifecycle-managed .instance property derived from the atom's value.

Depends on reatomInstance.

withInstance(create, dispose?)

When the source atom changes, the previous instance is disposed and a new one is created automatically.

Parameters

Parameter Type Description
create (target: T) => I Factory receiving the source atom
dispose (instance: I) => void Cleanup callback (optional)

Example

import { atom } from '@reatom/core'
import { withInstance } from '#reatom/extension/with-instance'

const dimensions = atom({ x: 1, y: 1, z: 1 }).extend(
  withInstance(
    (dims) => new BoxGeometry(dims().x, dims().y, dims().z),
    (geometry) => geometry.dispose(),
  ),
)

// Access the managed instance via .instance
const unsub = dimensions.instance.subscribe((geometry) => {
  scene.add(new Mesh(geometry, material))
})

// When dimensions change, old geometry is disposed,
// new one is created automatically.
dimensions.set({ x: 2, y: 3, z: 4 })

Composing instances

Instances created with withInstance can be consumed by other reatomInstance calls, forming reactive dependency chains:

import { reatomInstance } from '#reatom/factory/reatom-instance'

const material = atom({ color: '#00ff00' }).extend(
  withInstance(
    (params) => new MeshStandardMaterial({ color: params().color }),
    (mat) => mat.dispose(),
  ),
)

const mesh = reatomInstance(
  () => new Mesh(dimensions.instance(), material.instance()),
  (m) => m.removeFromParent(),
)

Example

import { atom, effect, withComputed } from '@reatom/core'

import { reatomInstance } from './reatom-instance'
import { withInstance } from './with-instance'

// --- Derive an instance from an atom ---

const config = atom({ width: 800, height: 600 }, 'config').extend(
  withInstance(
    (target) => {
      const { width, height } = target()
      const el = document.createElement('canvas')
      el.width = width
      el.height = height
      return el
    },
    (el) => el.remove(),
  ),
)

// Access the managed canvas via config.instance
effect(() => {
  document.body.appendChild(config.instance())
})

// --- Composing instances ---

const resolution = atom({ w: 1920, h: 1080 }, 'resolution').extend(
  withInstance(
    (res) => {
      const c = document.createElement('canvas')
      c.width = res().w
      c.height = res().h
      return c
    },
    (c) => c.remove(),
  ),
)

const renderer = reatomInstance(
  () => resolution.instance().getContext('2d')!,
).extend(
  withComputed((ctx) => {
    ctx.fillStyle = '#333'
    ctx.fillRect(
      0,
      0,
      resolution.instance().width,
      resolution.instance().height,
    )
    return ctx
  }),
)

// Subscribe to activate the chain
void renderer.subscribe(() => {})