diff --git a/packages/signals/README.md b/packages/signals/README.md index d1e772445..9a6f9e17c 100644 --- a/packages/signals/README.md +++ b/packages/signals/README.md @@ -106,7 +106,7 @@ use dioxus_signals::*; #[component] fn App(cx: Scope) -> Element { let signal = use_signal(cx, || 0); - let doubled = use_selector(cx, || signal * 2); + let doubled = use_selector(cx, move || signal * 2); render! { button { @@ -114,7 +114,7 @@ fn App(cx: Scope) -> Element { "Increase" } Child { - signal: signal + signal: doubled } } } diff --git a/packages/signals/examples/send.rs b/packages/signals/examples/send.rs new file mode 100644 index 000000000..9dda4480e --- /dev/null +++ b/packages/signals/examples/send.rs @@ -0,0 +1,26 @@ +use dioxus::prelude::*; +use dioxus_signals::*; + +fn main() { + tracing_subscriber::fmt::init(); + dioxus_desktop::launch(App); +} + +#[component] +fn App(cx: Scope) -> Element { + let mut signal = use_signal_sync(cx, || 0); + cx.use_hook(|| { + std::thread::spawn(move || loop { + std::thread::sleep(std::time::Duration::from_secs(1)); + signal += 1; + }) + }); + + render! { + button { + onclick: move |_| signal += 1, + "Increase" + } + "{signal}" + } +} diff --git a/packages/signals/src/impls.rs b/packages/signals/src/impls.rs index 4983f1f33..676101b20 100644 --- a/packages/signals/src/impls.rs +++ b/packages/signals/src/impls.rs @@ -36,6 +36,12 @@ macro_rules! read_impls { self.with(|v| Debug::fmt(v, f)) } } + + impl PartialEq for $ty { + fn eq(&self, other: &T) -> bool { + self.with(|v| *v == *other) + } + } }; } diff --git a/packages/signals/src/lib.rs b/packages/signals/src/lib.rs index 886f7a1f1..f2876f4a5 100644 --- a/packages/signals/src/lib.rs +++ b/packages/signals/src/lib.rs @@ -15,3 +15,4 @@ pub(crate) mod signal; pub use signal::*; mod dependency; pub use dependency::*; +pub use generational_box::{Storage, SyncStorage, UnsyncStorage}; diff --git a/packages/signals/src/signal.rs b/packages/signals/src/signal.rs index c04fcbc46..0c89e06a5 100644 --- a/packages/signals/src/signal.rs +++ b/packages/signals/src/signal.rs @@ -11,7 +11,9 @@ use dioxus_core::{ prelude::{current_scope_id, has_context, provide_context, schedule_update_any}, ScopeId, ScopeState, }; -use generational_box::{GenerationalBoxId, Mappable, MappableMut, Storage, UnsyncStorage}; +use generational_box::{ + GenerationalBoxId, Mappable, MappableMut, Storage, SyncStorage, UnsyncStorage, +}; use parking_lot::RwLock; use crate::{get_effect_ref, CopyValue, EffectStackRef, EFFECT_STACK}; @@ -59,7 +61,7 @@ pub fn use_signal(cx: &ScopeState, f: impl FnOnce() -> T) -> Signal< /// use dioxus_signals::*; /// /// fn App(cx: Scope) -> Element { -/// let mut count = use_signal(cx, || 0); +/// let mut count = use_signal_sync(cx, || 0); /// /// // Because signals have automatic dependency tracking, if you never read them in a component, that component will not be re-rended when the signal is updated. /// // The app component will never be rerendered in this example. @@ -67,7 +69,7 @@ pub fn use_signal(cx: &ScopeState, f: impl FnOnce() -> T) -> Signal< /// } /// /// #[component] -/// fn Child(cx: Scope, state: Signal) -> Element { +/// fn Child(cx: Scope, state: Signal) -> Element { /// let state = *state; /// /// use_future!(cx, |()| async move { @@ -90,8 +92,8 @@ pub fn use_signal(cx: &ScopeState, f: impl FnOnce() -> T) -> Signal< pub fn use_signal_sync( cx: &ScopeState, f: impl FnOnce() -> T, -) -> Signal { - *cx.use_hook(|| Signal::new(f())) +) -> Signal { + *cx.use_hook(|| Signal::new_maybe_sync(f())) } #[derive(Clone)] diff --git a/packages/signals/tests/selector.rs b/packages/signals/tests/selector.rs index 811871e88..44321bd0f 100644 --- a/packages/signals/tests/selector.rs +++ b/packages/signals/tests/selector.rs @@ -24,7 +24,7 @@ fn memos_rerun() { counter.borrow_mut().component += 1; let mut signal = use_signal(cx, || 0); - let memo = cx.use_hook(move || { + let memo = *cx.use_hook(move || { to_owned![counter]; selector(move || { counter.borrow_mut().effect += 1; @@ -32,9 +32,17 @@ fn memos_rerun() { signal.value() }) }); - assert_eq!(memo.value(), 0); + let generation = use_signal(cx, || cx.generation()); + generation.set(cx.generation()); + dioxus_signals::use_effect(cx, move || { + if generation == 1 { + assert_eq!(memo.value(), 0); + } + if generation == 3 { + assert_eq!(memo.value(), 1); + } + }); signal += 1; - assert_eq!(memo.value(), 1); render! { div {} @@ -44,14 +52,15 @@ fn memos_rerun() { ); let _ = dom.rebuild().santize(); + let _ = dom.render_immediate(); let current_counter = counter.borrow(); assert_eq!(current_counter.component, 1); assert_eq!(current_counter.effect, 2); } -#[test] -fn memos_prevents_component_rerun() { +#[tokio::test] +async fn memos_prevents_component_rerun() { let _ = simple_logger::SimpleLogger::new().init(); #[derive(Default)] @@ -126,6 +135,7 @@ fn memos_prevents_component_rerun() { let _ = dom.rebuild().santize(); dom.mark_dirty(ScopeId::ROOT); dom.render_immediate(); + dom.render_immediate(); { let current_counter = counter.borrow();