Skip to main content

State Management

marimo provides mo.state() for managing mutable reactive state in your notebooks. While marimo’s built-in reactivity handles most use cases, state() enables advanced patterns like synchronized UI elements and side effects.
Reactive state is an advanced feature that can introduce cycles and hard-to-debug execution paths. In almost all cases, you should prefer using marimo’s built-in reactive execution and interactivity.

Understanding marimo.state()

The mo.state() function creates mutable reactive state that triggers automatic re-execution of dependent cells when updated.

Basic Usage

This returns:
  • Getter function: Reads the current state value
  • Setter function: Updates the state value and triggers reactivity

Reading State

Updating State

Reactivity Behavior

When you call a state setter:
  1. The state value is updated
  2. All other cells that reference the getter are automatically re-run
  3. By default, the cell that called the setter is not re-run (preventing infinite loops)

Self-Loops

To allow a cell to re-run itself when calling the setter:
Use allow_self_loops=True carefully - ensure your logic has a termination condition to prevent infinite loops.

Common Use Cases

Synchronizing Multiple UI Elements

Bind multiple UI elements to shared state so they stay synchronized:
When either element is updated, both will reflect the new value automatically.

Tracking User Interactions

Building State Machines

Implementation Details

State Registry

marimo maintains a state registry that tracks all state instances in your notebook. From marimo/_runtime/state.py:
The registry:
  • Uses weak references to avoid memory leaks
  • Prunes inactive states when cells are deleted
  • Maintains bidirectional mappings for efficient lookups

SetFunctor

The setter is implemented as a typed functor that handles both direct values and functional updates:

Best Practices

State is ideal for keeping multiple UI elements in sync or managing UI-driven side effects.
Never store marimo.ui elements in state - this can cause hard-to-diagnose bugs and breaks reactivity.
For most cases, marimo’s automatic reactivity is sufficient:
Always use the setter function - never mutate the state value directly.

Testing State

From the test suite (tests/_runtime/test_state.py):

When to Use State

Use mo.state() when:
  • Synchronizing multiple UI elements to the same value
  • Implementing complex UI interaction patterns
  • Building state machines or multi-step workflows
  • Triggering side effects from UI interactions
Don’t use mo.state() when:
  • Simple variable assignment works (use marimo’s built-in reactivity)
  • You’re just reading UI element values (use .value directly)
  • You need to store computation results (use regular variables)