examples/concepts/state/README.md
This collection demonstrates various patterns for handling both mutable and immutable state in Ratatui applications. Each example solves a counter problem - incrementing a counter value - but uses different architectural approaches. These patterns represent common solutions to state management challenges you'll encounter when building TUI applications.
For more information about widgets in Ratatui, see the widgets module documentation.
Choose the pattern that best fits your application's architecture and complexity:
render-function or mutable-widget patternsstateful-widget or component-trait patternsnested-* patterns for parent-child relationshipsrefcell when multiple widgets need access to the same statewidget-with-mutable-ref when you understand Rust lifetimes wellTo run any example, use:
cargo run --bin example-name
Press any key (or resize the terminal) to increment the counter. Press <Esc> or q to exit.
These patterns keep widget state immutable during rendering, with state updates happening outside the render cycle. They're generally easier to reason about and less prone to borrowing issues.
immutable-function.rs - Function-Based Immutable StateBest for: Simple applications with pure rendering functions Pros: Pure functions, easy to test, clear separation of concerns Cons: Verbose parameter passing, limited integration with Ratatui ecosystem
Uses standalone functions that take immutable references to state. State updates happen in the application loop outside of rendering.
immutable-shared-ref.rs - Shared Reference Pattern (Recommended)Best for: Most modern Ratatui applications Pros: Reusable widgets, efficient, integrates with Ratatui ecosystem, modern best practice Cons: Requires external state management for dynamic behavior
Implements Widget for
&T, allowing widgets to be rendered multiple times by reference without being consumed.
immutable-consuming.rs - Consuming Widget PatternBest for: Compatibility with older code, simple widgets created fresh each frame Pros: Simple implementation, widely compatible, familiar pattern Cons: Widget consumed on each render, requires reconstruction for reuse
Implements Widget directly
on the owned type, consuming the widget when rendered.
These patterns allow widgets to modify their state during rendering, useful for widgets that need to update state as part of their rendering behavior.
mutable-function.rs - Function-Based Mutable StateBest for: Simple applications with minimal mutable state Pros: Easy to understand, no traits to implement, direct control Cons: State gets passed around as function parameters, harder to organize as complexity grows
Uses simple functions that accept mutable state references. State is managed at the application level and passed down to render functions.
mutable-widget.rs - Mutable Widget PatternBest for: Self-contained widgets with their own mutable state
Pros: Encapsulates state within the widget, familiar OOP-style approach
Cons: Requires &mut references, can be challenging with complex borrowing scenarios
Implements Widget for
&mut T, allowing the widget to mutate its own state during rendering.
stateful-widget.rs - Stateful Widget PatternBest for: Clean separation of widget logic from state Pros: Separates widget logic from state, reusable, idiomatic Ratatui pattern Cons: State must be managed externally
Uses StatefulWidget
to keep rendering logic separate from state management.
component-trait.rs - Custom Component TraitBest for: Implementing consistent behavior across multiple widget types Pros: Flexible, allows custom render signatures, good for widget frameworks Cons: Non-standard, requires users to learn your custom API
Creates a custom trait similar to Widget
but with a &mut self render method for direct mutation.
nested-mutable-widget.rs - Nested Mutable WidgetsBest for: Parent-child widget relationships with mutable state Pros: Hierarchical organization, each widget manages its own state Cons: Complex borrowing, requires careful lifetime management
Demonstrates how to nest widgets that both need mutable access to their state.
nested-stateful-widget.rs - Nested Stateful WidgetsBest for: Complex applications with hierarchical state management Pros: Clean separation, composable, scales well with application complexity Cons: More boilerplate, requires understanding of nested state patterns
Shows how to compose multiple StatefulWidgets
in a parent-child hierarchy.
refcell.rs - Interior Mutability PatternBest for: Shared state across multiple widgets, complex state sharing scenarios Pros: Allows shared mutable access, works with immutable widget references Cons: Runtime borrow checking, potential panics, harder to debug
Uses Rc<RefCell<T>> for interior mutability
when multiple widgets need access to the same state.
widget-with-mutable-ref.rs - Lifetime-Based Mutable ReferencesBest for: Advanced users who need precise control over state lifetime Pros: Zero-cost abstraction, explicit lifetime management Cons: Complex lifetimes, requires deep Rust knowledge, easy to get wrong
Stores mutable references directly in widget structs using explicit lifetimes.
For most applications, start with immutable patterns:
immutable-function for basic rendering with external state managementimmutable-shared-ref for reusable, efficient widgets (recommended)immutable-consuming when working with older code patternsUse mutable patterns when widgets need to update state during rendering:
mutable-function or mutable-widget for prototypesstateful-widget when you want to separate widget logic from statenested-* patterns for complex widget relationshipsrefcell when multiple widgets need the same statewidget-with-mutable-ref for advanced lifetime managementStatefulWidget
often provides the cleanest solution.refcell or widget-with-mutable-ref
unless you actually need them.