--- name: gpui-global description: Global state management in GPUI. Use when implementing global state, app-wide configuration, or shared resources. --- ## 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 ```rust use gpui::Global; #[derive(Clone)] struct AppSettings { theme: Theme, language: String, } impl Global for AppSettings {} ``` ### Set and Access Globals ```rust 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::(); println!("Theme: {:?}", settings.theme); }); } ``` ### Update Globals ```rust impl MyComponent { fn change_theme(&mut self, new_theme: Theme, cx: &mut Context) { cx.update_global::(|settings, cx| { settings.theme = new_theme; // Global updates don't trigger automatic notifications // Manually notify components that care }); cx.notify(); // Re-render this component } } ``` ## Common Use Cases ### 1. App Configuration ```rust #[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::(); ``` ### 2. Feature Flags ```rust #[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 { let flags = cx.global::(); if flags.enable_beta_features { Some(div().child("Beta feature")) } else { None } } } ``` ### 3. Shared Services ```rust #[derive(Clone)] struct ServiceRegistry { http_client: Arc, logger: Arc, } impl Global for ServiceRegistry {} impl MyComponent { fn fetch_data(&mut self, cx: &mut Context) { let registry = cx.global::(); let client = registry.http_client.clone(); 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 ```rust #[derive(Clone)] struct GlobalState { database: Arc, // Cheap to clone cache: Arc>, } impl Global for GlobalState {} ``` ### ✅ Immutable by Default Globals are read-only by default. Use interior mutability when needed: ```rust #[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 ```rust // ❌ 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](references/api-reference.md) - Global trait, set_global, update_global - Interior mutability patterns - Best practices and anti-patterns