Overview
Global state in GPUI provides app-wide shared data accessible from any context.
Key Trait: Global - Implement on types to make them globally accessible
Quick Start Define Global State use gpui::Global;
[derive(Clone)]
struct AppSettings { theme: Theme, language: String, }
impl Global for AppSettings {}
Set and Access Globals fn main() { let app = Application::new(); app.run(|cx: &mut App| { // Set global cx.set_global(AppSettings { theme: Theme::Dark, language: "en".to_string(), });
// Access global (read-only)
let settings = cx.global::<AppSettings>();
println!("Theme: {:?}", settings.theme);
});
}
Update Globals
impl MyComponent {
fn change_theme(&mut self, new_theme: Theme, cx: &mut Context
cx.notify(); // Re-render this component
}
}
Common Use Cases 1. App Configuration
[derive(Clone)]
struct AppConfig { api_endpoint: String, max_retries: u32, timeout: Duration, }
impl Global for AppConfig {}
// Set once at startup cx.set_global(AppConfig { api_endpoint: "https://api.example.com".to_string(), max_retries: 3, timeout: Duration::from_secs(30), });
// Access anywhere
let config = cx.global::
- Feature Flags
[derive(Clone)]
struct FeatureFlags { enable_beta_features: bool, enable_analytics: bool, }
impl Global for FeatureFlags {}
impl MyComponent {
fn render_beta_feature(&self, cx: &App) -> Option
if flags.enable_beta_features {
Some(div().child("Beta feature"))
} else {
None
}
}
}
- Shared Services
[derive(Clone)]
struct ServiceRegistry {
http_client: Arc
impl Global for ServiceRegistry {}
impl MyComponent {
fn fetch_data(&mut self, cx: &mut Context
cx.spawn(async move |cx| {
let data = client.get("api/data").await?;
// Process data...
Ok::<_, anyhow::Error>(())
}).detach();
}
}
Best Practices ✅ Use Arc for Shared Resources
[derive(Clone)]
struct GlobalState {
database: Arc
impl Global for GlobalState {}
✅ Immutable by Default
Globals are read-only by default. Use interior mutability when needed:
[derive(Clone)]
struct Counter {
count: Arc
impl Global for Counter {}
impl Counter { fn increment(&self) { self.count.fetch_add(1, Ordering::SeqCst); }
fn get(&self) -> usize {
self.count.load(Ordering::SeqCst)
}
}
❌ Don't: Overuse Globals // ❌ Bad: Too many globals cx.set_global(UserState { ... }); cx.set_global(CartState { ... }); cx.set_global(CheckoutState { ... });
// ✅ Good: Use entities for component state let user_entity = cx.new(|_| UserState { ... });
When to Use
Use Globals for:
App-wide configuration Feature flags Shared services (HTTP client, logger) Read-only reference data
Use Entities for:
Component-specific state State that changes frequently State that needs notifications Reference Documentation API Reference: See api-reference.md Global trait, set_global, update_global Interior mutability patterns Best practices and anti-patterns