Control flow syntax
control_flow demonstrates a core design of element!: the UI tree is part of ordinary Rust expressions. You can write if, if let, for, and match inside the tree, and different branches may return different element types without manually converting everything to AnyElement in application code.

This recording is generated by docs/tapes/control-flow.tape and runs examples/core/control_flow.rs. It moves the highlighted row, toggles the count between odd and even branches, and disables the optional name so if let falls through to else if.
Run it
Section titled “Run it”Press j/k to change the count and highlighted row, n to toggle the optional name, and q to exit.
Branches can return different elements
Section titled “Branches can return different elements”The two sides of if / else do not have to be the same component type. This branch returns Text on one side and a bordered Border subtree on the other:
The macro converges those branches into element declarations the framework can reconcile. Each branch only needs to produce a valid element.
if let fits optional data
Section titled “if let fits optional data”Optional data can be expanded directly inside the tree:
This style works well for loading states, empty states, permission branches, and optional context. Do not first push an optional block into a temporary Vec just to render it; writing it directly in element! is usually clearer.
for still needs stable keys
Section titled “for still needs stable keys”for can generate rows directly, but list items still need stable keys:
In the example, ROWS is a static array, so index is stable enough. In real business lists that can insert, delete, or reorder items, prefer business IDs as keys to avoid reusing state on the wrong row.
match fits state-machine views
Section titled “match fits state-machine views”When page state is naturally an enum, step, or mode, match is easier to read than several booleans:
Each match arm wraps its element in { ... }; that keeps complex subtrees clear and avoids macro parsing ambiguity.
Relationship to the component model
Section titled “Relationship to the component model”element! rebuilds lightweight declarations every frame; persistent state lives in reconciled Component instances. When control flow changes, the runtime uses ElementKey + TypeId to decide which nodes can be reused and which should be recreated.
Next, return to the component model to understand keys and instance reuse, or continue to Hooks to learn why state remains stable across branch changes and redraws.