Browse Source

feat(examples): add Context API state management example (#3657)

* feat(examples): add Context API state management example (fixes #3612)

* refactor: code cleanup
Z 4 months ago
parent
commit
68ca4c3289
3 changed files with 134 additions and 0 deletions
  1. 2 0
      examples/README.md
  2. 43 0
      examples/assets/context_api.css
  3. 89 0
      examples/context_api.rs

+ 2 - 0
examples/README.md

@@ -52,6 +52,8 @@ cargo run --example hello_world
 
 ### State Management
 
+[context_api](./context_api.rs) - Cross-component state sharing via Context API
+
 ### Async
 
 [login_form](./login_form.rs) - Login endpoint example

+ 43 - 0
examples/assets/context_api.css

@@ -0,0 +1,43 @@
+.main-container {
+  font-family: system-ui, sans-serif;
+  max-width: 600px;
+  margin: 2rem auto;
+  padding: 2rem;
+}
+
+.light-theme {
+  background: #ffffff;
+  color: #1a1a1a;
+  border: 1px solid #e0e0e0;
+}
+
+.dark-theme {
+  background: #1a1a1a;
+  color: #ffffff;
+  border: 1px solid #333;
+}
+
+.controls {
+  display: flex;
+  gap: 1rem;
+  margin: 2rem 0;
+}
+
+.btn {
+  padding: 0.5rem 1rem;
+  border: none;
+  border-radius: 4px;
+  cursor: pointer;
+  transition: opacity 0.2s;
+}
+
+.btn:disabled {
+  opacity: 0.7;
+  cursor: not-allowed;
+}
+
+.display {
+  padding: 2rem;
+  border-radius: 8px;
+  margin-top: 2rem;
+}

+ 89 - 0
examples/context_api.rs

@@ -0,0 +1,89 @@
+//! Demonstrates cross-component state sharing using Dioxus' Context API
+//!
+//! Features:
+//! - Context provider initialization
+//! - Nested component consumption
+//! - Reactive state updates
+//! - Error handling for missing context
+//! - Platform-agnostic implementation
+
+use dioxus::prelude::*;
+
+const STYLE: Asset = asset!("/examples/assets/context_api.css");
+
+fn main() {
+    launch(app);
+}
+
+#[component]
+fn app() -> Element {
+    // Provide theme context at root level
+    use_context_provider(|| Signal::new(Theme::Light));
+
+    rsx! {
+        document::Link { rel: "stylesheet", href: STYLE }
+        main {
+            class: "main-container",
+
+            h1 { "Theme Switcher" }
+            ThemeControls {}
+            ThemeDisplay {}
+        }
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Debug)]
+enum Theme {
+    Light,
+    Dark,
+}
+
+impl Theme {
+    fn stylesheet(&self) -> &'static str {
+        match self {
+            Theme::Light => "light-theme",
+            Theme::Dark => "dark-theme",
+        }
+    }
+}
+
+#[component]
+fn ThemeControls() -> Element {
+    let mut theme = use_theme_context();
+    let current_theme = *theme.read();
+    rsx! {
+        div {
+            class: "controls",
+            button {
+                class: "btn",
+                onclick: move |_| theme.set(Theme::Light),
+                disabled: current_theme== Theme::Light,
+                "Switch to Light"
+            }
+            button {
+                class: "btn",
+                onclick: move |_| theme.set(Theme::Dark),
+                disabled: current_theme == Theme::Dark,
+                "Switch to Dark"
+            }
+        }
+    }
+}
+
+#[component]
+fn ThemeDisplay() -> Element {
+    let theme = use_theme_context();
+
+    rsx! {
+        div {
+            class: "display {theme.read().stylesheet()}",
+            p { "Current theme: {theme:?}" }
+            p { "Try switching themes using the buttons above!" }
+        }
+    }
+}
+
+fn use_theme_context() -> Signal<Theme> {
+    try_use_context::<Signal<Theme>>()
+        .expect("Theme context not found. Ensure <App> is the root component.")
+}