瀏覽代碼

create some more compelling examples

Evan Almloff 1 年之前
父節點
當前提交
292b3367dd

+ 4 - 8
packages/core/src/scope_context.rs

@@ -180,14 +180,10 @@ impl ScopeContext {
     /// when a context already exists will swap the context out for the new one, which may not be what you want.
     pub fn provide_root_context<T: 'static + Clone>(&self, context: T) -> T {
         with_runtime(|runtime| {
-            // Walk upwards until there is no more parent - and tada we have the root
-            let mut parent = runtime.get_context(self.scope_id()).unwrap();
-            while let Some(next_parent) = parent.parent_id {
-                parent = runtime.get_context(next_parent).unwrap();
-            }
-            debug_assert_eq!(parent.scope_id(), ScopeId(0));
-
-            parent.provide_context(context)
+            runtime
+                .get_context(ScopeId(0))
+                .unwrap()
+                .provide_context(context)
         })
         .expect("Runtime to exist")
     }

+ 1 - 0
packages/generational-box/src/lib.rs

@@ -258,6 +258,7 @@ impl MemoryLocation {
         let old = self.data.borrow_mut().take();
         #[cfg(any(debug_assertions, feature = "check_generation"))]
         if old.is_some() {
+            drop(old);
             let new_generation = self.generation.get() + 1;
             self.generation.set(new_generation);
         }

+ 1 - 0
packages/signals/Cargo.toml

@@ -14,3 +14,4 @@ simple_logger = "4.2.0"
 
 [dev-dependencies]
 dioxus = { workspace = true }
+dioxus-desktop = { workspace = true }

+ 22 - 0
packages/signals/README.md

@@ -54,3 +54,25 @@ fn Child(cx: Scope<ChildProps>) -> Element {
     }
 }
 ```
+
+Because subscriptions happen when you read from (not create) the data, you can provide signals through the normal context API:
+
+```rust
+fn app(cx: Scope) -> Element {
+    // Because signal is never read in this component, this component will not rerun when the signal changes
+    use_context_provider(cx, || Signal::new(0));
+
+    render! {
+        Child {}
+    }
+}
+
+fn Child(cx: Scope) -> Element {
+    let signal: Signal<i32> = *use_context(cx).unwrap();
+    // This component does read from the signal, so when the signal changes it will rerun
+    render! {
+        "{signal}"
+    }
+}
+
+```

+ 25 - 0
packages/signals/examples/context.rs

@@ -0,0 +1,25 @@
+#![allow(non_snake_case)]
+
+use dioxus::prelude::*;
+use dioxus_signals::{use_signal, Effect, Signal};
+
+fn main() {
+    dioxus_desktop::launch(app);
+}
+
+fn app(cx: Scope) -> Element {
+    // Because signal is never read in this component, this component will not rerun when the signal changes
+    use_context_provider(cx, || Signal::new(0));
+
+    render! {
+        Child {}
+    }
+}
+
+fn Child(cx: Scope) -> Element {
+    let signal: Signal<i32> = *use_context(cx).unwrap();
+    // This component does read from the signal, so when the signal changes it will rerun
+    render! {
+        "{signal}"
+    }
+}

+ 150 - 0
packages/signals/examples/split_subscriptions.rs

@@ -0,0 +1,150 @@
+#![allow(non_snake_case)]
+
+use dioxus::prelude::*;
+use dioxus_signals::Signal;
+
+fn main() {
+    dioxus_desktop::launch(app);
+}
+
+#[derive(Clone, Copy, Default)]
+struct ApplicationData {
+    first_data: Signal<i32>,
+    second_data: Signal<i32>,
+    many_signals: Signal<Vec<Signal<i32>>>,
+}
+
+fn use_app_data(cx: Scope) -> ApplicationData {
+    *use_context(cx).unwrap()
+}
+
+fn app(cx: Scope) -> Element {
+    use_context_provider(cx, ApplicationData::default);
+
+    render! {
+        div {
+            ReadsFirst {}
+        }
+        div {
+            ReadsSecond {}
+        }
+        div {
+            ReadsManySignals {}
+        }
+    }
+}
+
+fn ReadsFirst(cx: Scope) -> Element {
+    println!("running first");
+    let data = use_app_data(cx);
+
+    render! {
+        button {
+            onclick: move |_| {
+                *data.first_data.write() += 1;
+            },
+            "Increase"
+        }
+        button {
+            onclick: move |_| {
+                *data.first_data.write() -= 1;
+            },
+            "Decrease"
+        }
+        button {
+            onclick: move |_| {
+                *data.first_data.write() = 0;
+            },
+            "Reset"
+        }
+        "{data.first_data}"
+    }
+}
+
+fn ReadsSecond(cx: Scope) -> Element {
+    println!("running second");
+    let data = use_app_data(cx);
+
+    render! {
+        button {
+            onclick: move |_| {
+                *data.second_data.write() += 1;
+            },
+            "Increase"
+        }
+        button {
+            onclick: move |_| {
+                *data.second_data.write() -= 1;
+            },
+            "Decrease"
+        }
+        button {
+            onclick: move |_| {
+                *data.second_data.write() = 0;
+            },
+            "Reset"
+        }
+        "{data.second_data}"
+    }
+}
+
+fn ReadsManySignals(cx: Scope) -> Element {
+    println!("running many signals");
+    let data = use_app_data(cx);
+
+    render! {
+        button {
+            onclick: move |_| {
+                data.many_signals.write().push(Signal::new(0));
+            },
+            "Create"
+        }
+        button {
+            onclick: move |_| {
+                data.many_signals.write().pop();
+            },
+            "Destroy"
+        }
+        button {
+            onclick: move |_| {
+                if let Some(first) = data.many_signals.read().get(0) {
+                    *first.write() += 1;
+                }
+            },
+            "Increase First Item"
+        }
+        for signal in data.many_signals {
+            Child {
+                count: signal,
+            }
+        }
+    }
+}
+
+#[derive(Props, PartialEq)]
+struct ChildProps {
+    count: Signal<i32>,
+}
+
+fn Child(cx: Scope<ChildProps>) -> Element {
+    println!("running child");
+    let count = cx.props.count;
+
+    render! {
+        div {
+            "Child: {count}"
+            button {
+                onclick: move |_| {
+                    *count.write() += 1;
+                },
+                "Increase"
+            }
+            button {
+                onclick: move |_| {
+                    *count.write() -= 1;
+                },
+                "Decrease"
+            }
+        }
+    }
+}