v0.20.230 - 9.5 / 6.1

Store

Utilities to make and modify reactive objects.

# Import

# API at a glance

namesignaturereturnspurpose
mutable(value, clone?)proxy of valuedeeply reactive proxy — every property (current and future) is tracked and mutable
signalify(target, keys?)targetone-level signalification — replaces the target's own properties (or the listed keys) with tracked getters/setters
merge(target, source, keys?)targetmerges source into target, preserving existing references
replace(target, source, keys?)targetlike merge, but also removes keys from target that are absent from source
reset(target, source)targetoverwrites the keys of target that appear in source with the values from source

All five utilities mutate target in place and return it for convenience; the returned reference is the same object you passed in.

# mutable

Wraps value in a proxy that turns every property into a signal, recursively. Both existing and new properties are tracked and mutable. Reads of keys that don't exist yet are still tracked — once the key is added, readers re-run.

mutable(obj) modifies obj in place so the original reference stays reactive (and identity methods like === keep working). Pass true as the second argument to copy the input first, leaving the original untouched.

mutable(obj, true) makes a copy first, so the original object stays unchanged.

# signalify

Like mutable, but shallow: only the target's own properties become tracked getters/setters. Nested objects stay plain objects. Useful for opt-in reactivity on a handful of keys without walking the whole tree.

All own properties become reactive.

Pass a keys array to signalify only the properties you name. The keys don't have to exist yet — reads of a missing key are tracked and will re-run once the key is assigned.

Only the lala property is made reactive.

# Reconcile: merge, replace, reset

Reconciling data can be confusing — there are three APIs so each use case stays narrow and explicit. In every case, the references to unchanged properties are kept intact.

All three accept an optional keys option (third argument on merge / replace) that tells the reconciler how to identify items inside nested arrays. Without it, entries are matched by index; with it, they are matched by the named key and references to unchanged items are preserved across reorderings.

# merge

Merges source into target. Keys of target that are absent from source are left alone.

With no keys option, nested arrays are merged positionally.
Passing { q: { key: 'id' } } tells merge to match entries inside q by id; unmatched items from source are appended.

# replace

Merges source into target and deletes any keys of target that aren't in source.

Same starting data as the merge example — here everything absent from source is removed.
With the keys option, rows are matched by id and references to items that survived the replace are preserved.

# reset

Overwrites keys of target that appear in source. Unlike replace, keys of target not in source are kept.

Building a mutable from a defaultState, then resetting part of it back to the defaults. Note the mutable(defaultState, true) copy — otherwise the mutable proxy would share references with defaultState.