internal-docs/guides/reactivity/system-phases.md
To allow developers to reason about reactive composition, developers typically interact with tags through higher-level abstractions that represent reactive values.
While reactive tags describe the formal composition semantics of the Glimmer system, "Reactive Values" describe the rules that higher-level abstractions must follow in order to allow developers to safely reason about reactive composition.
Glimmer's reactivity system combines three key elements that work together to provide a coherent reactive programming model:
A Tag-Based Validation System: As described in tag-composition.md, Glimmer uses tags to track and validate dependencies without requiring value recomputation.
The Fundamental Laws of Reactivity: The laws define the contracts that all reactive abstractions must adhere to, ensuring predictable behavior when abstractions are composed.
System Phases: The system operates in distinct phases that separate mutation from validation, enabling efficient tracking while preventing inconsistencies.
These elements combine to create a system where developers can write straightforward JavaScript code while the framework maintains reactivity behind the scenes. The phases of the system, in particular, provide the framework for implementing the laws in practice.
---
config:
theme: base
themeVariables:
primaryColor: "#b9cccc"
secondaryColor: "#ffffff"
tertiaryColor: "#ff0000"
background: "#f9ffff"
lineColor: "#005f5f"
mainBkg: "#9fe9e9"
textColor: "#005f5f"
---
stateDiagram
direction LR
state ReactiveLoop {
direction LR
Render --> Idle
Idle --> Action
Action --> Render
Render
Idle
Action
}
[*] --> Setup:App Boot
Setup --> Render:Initial Render
ReactiveLoop --> [*]:App cleanup
ReactiveLoop:Reactive Loop
Setup:Setup state
classDef transition fill:red
The action phase allows app code to update reactive state in response to a system event (such as a promise resolution) or a user event (such as an input event or button click).
During this phase, app code is permitted to freely read and write reactive values as if they were normal JavaScript values. This prepares the reactive state for the next phase, the render phase.
The render phase updates the UI to reflect any changes to the reactive state.
This phase is transactional, which means that reactive state is observably frozen for the duration of the render phase. Once a reactive value is accessed during a render transaction, any subsequent accesses will produce the same value at the same revision.
To satisfy the requirement that reactive state is observably frozen during a single render phase:
The idle phase represents a quiescent state where the UI is fully rendered and consistent with the current reactive state. During this phase:
The idle phase ends when an event occurs (user interaction, network response, timer, etc.) and the
event handler updates one or more reactive values (via the [Update] operation on a tag). This
transition the system into the action phase.
The system also schedules the render phase to run asynchronously after the current JavaScript job completes (consistent with JavaScript's run-to-completion semantics).
As a consequence of this design, all reactive updates that occur within the same JavaScript execution context are naturally batched together and processed in a single upcoming render phase.
It's important to understand that while updates to the rendered output (UI) are batched, the reactive values inside the system maintain full coherence at all times:
This automatic batching ensures optimal performance by preventing cascading rerenders while allowing developers to work with reactive values as if they were normal JavaScript values. From the developer's perspective, reactive computations behave just like normal functions, giving them a familiar programming model with the added benefit of automatic UI updates.