observableBox

observableBox is the simplest reactive primitive. It holds a single value and notifies observers whenever that value changes.

Signature

function observableBox<T>(
  initialValue: T,
  options?: BoxOptions,
): ObservableBox<T>

interface ObservableBox<T> {
  get(): T
  set(value: T): void
}

interface BoxOptions {
  name?: string
  comparer?: EqualityComparison
}

Parameters

Parameter Type Description
initialValue T The starting value
options.name string Debug name (defaults to Box@<id>)
options.comparer EqualityComparison How to determine if a value has changed

Basic usage

import { autorun, observableBox } from "@fobx/core"

const count = observableBox(0)

const stop = autorun(() => {
  console.log("count:", count.get())
})
// prints: count: 0

count.set(1)
// prints: count: 1

count.set(1)
// nothing printed — same value, default comparer blocks

stop()

Custom equality

By default, observableBox uses a comparer equivalent to strict equality with NaN handling. You can override this with the comparer option:

import { observableBox } from "@fobx/core"

// Built-in structural comparer (requires configure() setup)
const a = observableBox({ x: 1 }, { comparer: "structural" })

// Custom comparer function
const epsilon = observableBox(0, {
  comparer: (prev, next) => Math.abs(prev - next) < 0.001,
})

epsilon.set(0.0001) // no change — within threshold
epsilon.set(1) // change — outside threshold

Built-in comparers

Value Behavior
"default" Strict identity with NaN handling (the default)
"structural" Deep equality — requires configure({ comparer: { structural } })
(a, b) => boolean Custom function

When to use

Use observableBox for standalone reactive values that are not part of an observable object or class:

  • Global configuration flags
  • A single selected ID
  • A value shared between unrelated parts of your app

For reactive properties on an object, use observable() or makeObservable() instead.