Builds a callable hierarchical state tree from a nested list. The shape
rule is simple: a bare named list (length > 0) becomes a navigable
reactiveStore node (every sub-tree is itself a reactiveStore);
everything else becomes a plain shiny::reactiveVal() leaf that accepts
any value on write. To force a bare named list to be treated as a leaf
instead of a store, wrap it in base::I().
Arguments
- initial
A bare named list describing the initial shape. Sub-positions classify as follows: bare named lists (length > 0) become store sub-nodes; anything else (scalars, vectors,
NULL, unnamed/empty bare lists, classed lists, or any value wrapped inI()) becomes a leaf. Partially-named bare lists are an error.
Value
A callable reactiveStore node with class
c("reactiveStore", "reactive", "function"). Sub-trees share the
same class. Leaf positions are plain shiny::reactiveVal()s with
class c("reactiveVal", "reactive", "function") — the shared
"reactive" class is what auto-bind dispatches on.
Details
Every node is callable: node() reads, node(value) writes. Branch
writes replace: the input must list every locked key for that branch.
Both unknown keys and missing keys are an error. Types are not enforced.
Per-field writes (node$key(value)) remain the dedicated single-slot
path — use them when you want to update one field without naming the
rest.
length() on a leaf returns 1 (the underlying reactiveVal is a
callable, and neither R's closure default nor shiny override
length). htmltools' dropNullsOrEmpty calls length() on every
attribute value, so this is what lets value = state$leaf survive
tag construction. Use length(leaf()) for the underlying length.
