| name | gpui-entity |
| description | Entity management and state handling in GPUI. Use when working with entities, managing component state, coordinating between components, handling async operations with state updates, or implementing reactive patterns. Entities provide safe concurrent access to application state. |
Overview
An Entity<T> is a handle to state of type T, providing safe access and updates.
Key Methods:
entity.read(cx) → &T - Read-only access
entity.read_with(cx, |state, cx| ...) → R - Read with closure
entity.update(cx, |state, cx| ...) → R - Mutable update
entity.downgrade() → WeakEntity<T> - Create weak reference
entity.entity_id() → EntityId - Unique identifier
Entity Types:
Entity<T>: Strong reference (increases ref count)
WeakEntity<T>: Weak reference (doesn't prevent cleanup, returns Result)
Quick Start
Creating and Using Entities
let counter = cx.new(|cx| Counter { count: 0 });
let count = counter.read(cx).count;
counter.update(cx, |state, cx| {
state.count += 1;
cx.notify();
});
let weak = counter.downgrade();
let _ = weak.update(cx, |state, cx| {
state.count += 1;
cx.notify();
});
In Components
struct MyComponent {
shared_state: Entity<SharedData>,
}
impl MyComponent {
fn new(cx: &mut App) -> Entity<Self> {
let shared = cx.new(|_| SharedData::default());
cx.new(|cx| Self {
shared_state: shared,
})
}
fn update_shared(&mut self, cx: &mut Context<Self>) {
self.shared_state.update(cx, |state, cx| {
state.value = 42;
cx.notify();
});
}
}
Async Operations
impl MyComponent {
fn fetch_data(&mut self, cx: &mut Context<Self>) {
let weak_self = cx.entity().downgrade();
cx.spawn(async move |cx| {
let data = fetch_from_api().await;
let _ = weak_self.update(cx, |state, cx| {
state.data = Some(data);
cx.notify();
});
}).detach();
}
}
Core Principles
Always Use Weak References in Closures
let weak = cx.entity().downgrade();
callback(move || {
let _ = weak.update(cx, |state, cx| cx.notify());
});
let strong = cx.entity();
callback(move || {
strong.update(cx, |state, cx| cx.notify());
});
Use Inner Context
entity.update(cx, |state, inner_cx| {
inner_cx.notify();
});
entity.update(cx, |state, inner_cx| {
cx.notify();
});
Avoid Nested Updates
entity1.update(cx, |state, cx| { });
entity2.update(cx, |state, cx| { });
entity1.update(cx, |_, cx| {
entity2.update(cx, |_, cx| { });
});
Common Use Cases
- Component State: Internal state that needs reactivity
- Shared State: State shared between multiple components
- Parent-Child: Coordinating between related components (use weak refs)
- Async State: Managing state that changes from async operations
- Observations: Reacting to changes in other entities
Reference Documentation
Complete API Documentation
- Entity API: See api-reference.md
- Entity types, methods, lifecycle
- Context methods, async operations
- Error handling, type conversions
Implementation Guides
-
Patterns: See patterns.md
- Model-view separation, state management
- Cross-entity communication, async operations
- Observer pattern, event subscription
- Pattern selection guide
-
Best Practices: See best-practices.md
- Avoiding common pitfalls, memory leaks
- Performance optimization, batching updates
- Lifecycle management, cleanup
- Async best practices, testing
-
Advanced Patterns: See advanced.md
- Entity collections, registry pattern
- Debounced/throttled updates, state machines
- Entity snapshots, transactions, pools