How Updates Work

What happens between changing a property and seeing the DOM update, in four steps.

The Mental Model: Write normal JavaScript. Mutate state. The DOM updates. This page explains the machinery that makes that possible.

The Update Pipeline

Every DOM update in WildflowerJS follows the same four-step pipeline:

The Update Pipeline: 1. State Change (this.count++) → 2. Dependency Lookup (which bindings read count?) → 3. Effects Scheduled (changes coalesce into one update) → 4. Targeted DOM Updates (only affected nodes are touched)

This pipeline runs automatically. You never interact with it directly. Just change state and the framework handles the rest.

Step by Step

1. State Change: Proxy Interception

WildflowerJS wraps component state in a JavaScript Proxy. When you assign a property, the Proxy's set trap fires:

// You write:
this.count++

// The Proxy intercepts this as:
// set(target, 'count', 1)
// → records that 'count' changed
// → schedules an update

This works for any mutation: direct assignment, nested property changes, array methods:

this.count++                    // direct assignment
this.user.name = "Jane"         // nested property
this.items.push({ text: "New" }) // array mutation
this.items.splice(2, 1)         // array splice

All of these are intercepted automatically. There is no special syntax, wrapper function, or immutable update pattern to follow.

2. Dependency Lookup: Path-Level Tracking

When the framework processes a binding like data-bind="count", it records that this specific DOM node depends on the count property. This creates a mapping:

Property Path    →    DOM Nodes
─────────────         ─────────
count            →    span#counter-display
user.name        →    h1#greeting, span#profile-name
items            →    ul#todo-list (list binding)
items[].text     →    each li text node

When count changes, the framework looks up exactly which nodes depend on it. Nothing walks the tree, re-renders a component, or diffs. Just a direct lookup.

Computed properties live in the same graph. State, computeds, effects, and bindings are all nodes in one dependency graph, so a binding that reads a computed depends, through it, on the state the computed reads; a change wakes the chain and nothing else.

3. Effects Scheduled: Automatic Batching

Changes made in the same synchronous block coalesce. Some updates apply at the moment of the write and others are queued and flushed together on a microtask; which is which is an internal optimization detail that may change between releases. The guarantee to build on is simple: by the time your await, timeout, or next event handler runs, the DOM reflects your state, and within any frame the user sees a consistent picture.

// All three changes happen synchronously
this.firstName = "Jane"
this.lastName = "Smith"
this.email = "jane@example.com"

// The DOM settles with the final values.
// No half-applied state ever reaches the screen.

This is automatic. You never need to wrap changes in a batch function or call a flush method, and you should not build on intra-tick DOM timing; coalescing happens on its own.

4. Targeted DOM Updates: Surgical Precision

When the microtask fires, only the specific DOM nodes that depend on changed properties are updated:

<div data-component="profile">
    <h1 data-bind="name"></h1>       <!-- Updated ✓ -->
    <p data-bind="bio"></p>         <!-- NOT touched -->
    <span data-bind="email"></span>  <!-- NOT touched -->
</div>

If only name changed, only the <h1> is touched. The <p> and <span> are untouched. The framework doesn't even look at them.

How This Differs from Virtual DOM

Virtual DOM (React, Vue)
  1. State changes
  2. Re-render entire component to virtual tree
  3. Diff old virtual tree vs new virtual tree
  4. Compute minimal set of DOM patches
  5. Apply patches to real DOM

Work is proportional to component size

WildflowerJS
  1. State changes
  2. Look up which bindings depend on changed path
  3. Update those DOM nodes directly

Work is proportional to number of changes

Virtual DOM frameworks do work proportional to component size (they must re-render and diff the entire component). WildflowerJS does work proportional to what actually changed: if one property changed and two DOM nodes depend on it, only those two nodes are touched regardless of how large the component is.

List Updates: Operation Detection

Lists get special treatment. Instead of re-rendering the entire list when an array changes, WildflowerJS detects what kind of operation occurred and applies the minimal DOM change:

Array Operation DOM Response
items.push(item) Append one new node
items.pop() Remove last node
items.splice(2, 1) Remove node at index 2
items.unshift(item) Prepend one new node
items[i] = newItem Update node at index i in place
items = [...items].sort(fn) Reconcile with minimal moves

Nested Reactivity

The Proxy wrapping is deep: it covers nested objects and arrays automatically:

// All of these trigger updates automatically:
this.user.address.city = "Portland"    // deep nested property
this.columns[2].cards.push(newCard)    // nested array mutation
this.settings = { ...this.settings, theme: "dark" }  // object replacement

There is no depth limit. The framework tracks changes at whatever level they occur and updates only the bindings that depend on the changed path.

What This Means for You

Write natural JavaScript. Assign properties, push to arrays, mutate nested objects. The framework detects changes, finds affected DOM nodes, batches updates, and applies them precisely, all automatically. You focus on your application logic; the framework handles the DOM.