Skip to content

Helper Functions


opaqueObject marks an object in an observable as opaque so that it will be treated as a primitive, so that properties inside the opaque object will not be observable.

This is useful for storing DOM or React elements or other large objects in an observable when you don’t care about tracking its properties changing.

import { observable. opaqueObject } from '@legendapp/state'

const state$ = observable({ text: 'hi', body: opaqueObject(document.body) })


If you want to merge a deep object into an observable, mergeIntoObservable can do that and retain all of the existing observables and listeners on the way, and fire listeners as values change. This is used by persistObservable under the hood.

import { observable } from "@legendapp/state";
import { mergeIntoObservable } from "@legendapp/state";

const state$ = observable({ store: { text: "hello", other: "hello there" } });

state$.store.text.onChange(({ value }) =>
  console.log(`text changed to "${value}"`)

const newValue = { store: { text: "hi", other: "hi there" } };
mergeIntoObservable(state$, newValue);

// text changed to "hi"

state$.store ===; // ✅ true


To ensure that observables are only modified within certain actions, you can lock observables so that they cannot be modified, then unlock them temporarily in your actions. This is used under the hood by computed.

import { lockObservable, observable } from '@legendapp/state'

const state$ = observable({ store: { ... } })
lockObservable(state$, true)

function safeAction() {
    // Unlock it to modify it
    lockObservable(state$, false)
    // Modify it
    state$.set({ store: { ... } })
    // Lock it back
    lockObservable(state$, true)


trackHistory creates an observable that tracks all changes in the target observable, with the previous value at the time it was changed.

Since the history is an observable you can observe it or persist it like any other observable. This can be useful for saving a version history for a text editor or creating an undo stack.

An optional second parameter lets you use an existing observable for storing the history, which can be useful to save history into an existing state object.

import { observable } from '@legendapp/state'
import { trackHistory } from '@legendapp/state/history'

const state = observable({ profile: { name: 'Hello' }})

// Track all changes to state
const history = trackHistory(state)

// Change something in state'Annyong')

// History shows the previous value when it changed:
    1666593133018: {
        profile: {
            name: 'Hello'