gpui-entity
SKILL.md
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 accessentity.read_with(cx, |state, cx| ...)→R- Read with closureentity.update(cx, |state, cx| ...)→R- Mutable updateentity.downgrade()→WeakEntity<T>- Create weak referenceentity.entity_id()→EntityId- Unique identifier
Entity Types:
Entity<T>: Strong reference (increases ref count)WeakEntity<T>: Weak reference (doesn't prevent cleanup, returnsResult)
Quick Start
Creating and Using Entities
// Create entity
let counter = cx.new(|cx| Counter { count: 0 });
// Read state
let count = counter.read(cx).count;
// Update state
counter.update(cx, |state, cx| {
state.count += 1;
cx.notify(); // Trigger re-render
});
// Weak reference (for closures/callbacks)
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;
// Update entity safely
let _ = weak_self.update(cx, |state, cx| {
state.data = Some(data);
cx.notify();
});
}).detach();
}
}
Core Principles
Always Use Weak References in Closures
// ✅ Good: Weak reference prevents retain cycles
let weak = cx.entity().downgrade();
callback(move || {
let _ = weak.update(cx, |state, cx| cx.notify());
});
// ❌ Bad: Strong reference may cause memory leak
let strong = cx.entity();
callback(move || {
strong.update(cx, |state, cx| cx.notify());
});
Use Inner Context
// ✅ Good: Use inner cx from closure
entity.update(cx, |state, inner_cx| {
inner_cx.notify(); // Correct
});
// ❌ Bad: Use outer cx (multiple borrow error)
entity.update(cx, |state, inner_cx| {
cx.notify(); // Wrong!
});
Avoid Nested Updates
// ✅ Good: Sequential updates
entity1.update(cx, |state, cx| { /* ... */ });
entity2.update(cx, |state, cx| { /* ... */ });
// ❌ Bad: Nested updates (may panic)
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
Weekly Installs
127
Repository
longbridge/gpui…omponentGitHub Stars
10.7K
First Seen
Jan 21, 2026
Security Audits
Installed on
opencode113
codex105
gemini-cli105
github-copilot96
cursor93
claude-code92