From 38274da3ee10ea04948440517b6eef92f90e4b71 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Mon, 21 Aug 2023 14:42:56 -0500 Subject: [PATCH 1/2] Fix creating signals in effects --- packages/signals/src/effect.rs | 2 ++ packages/signals/src/rt.rs | 25 ++++++++++++++++--------- packages/signals/src/selector.rs | 1 + 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/packages/signals/src/effect.rs b/packages/signals/src/effect.rs index 0685938a0..1a42c227f 100644 --- a/packages/signals/src/effect.rs +++ b/packages/signals/src/effect.rs @@ -54,6 +54,7 @@ pub fn use_effect_with_dependencies( /// Effects allow you to run code when a signal changes. Effects are run immediately and whenever any signal it reads changes. #[derive(Copy, Clone, PartialEq)] pub struct Effect { + pub(crate) source: ScopeId, pub(crate) callback: CopyValue>, } @@ -73,6 +74,7 @@ impl Effect { /// The signal will be owned by the current component and will be dropped when the component is dropped. pub fn new(callback: impl FnMut() + 'static) -> Self { let myself = Self { + source: current_scope_id().expect("in a virtual dom"), callback: CopyValue::new(Box::new(callback)), }; diff --git a/packages/signals/src/rt.rs b/packages/signals/src/rt.rs index 7322d43b4..113fe9b30 100644 --- a/packages/signals/src/rt.rs +++ b/packages/signals/src/rt.rs @@ -2,14 +2,13 @@ use std::cell::{Ref, RefMut}; use std::rc::Rc; -use dioxus_core::prelude::{ - consume_context, consume_context_from_scope, current_scope_id, provide_context, - provide_context_to_scope, provide_root_context, -}; +use dioxus_core::prelude::*; use dioxus_core::ScopeId; use generational_box::{GenerationalBox, Owner, Store}; +use crate::Effect; + fn current_store() -> Store { match consume_context() { Some(rt) => rt, @@ -21,12 +20,20 @@ fn current_store() -> Store { } fn current_owner() -> Rc { - match consume_context() { - Some(rt) => rt, - None => { - let owner = Rc::new(current_store().owner()); - provide_context(owner).expect("in a virtual dom") + match Effect::current() { + // If we are inside of an effect, we should use the owner of the effect as the owner of the value. + Some(effect) => { + let scope_id = effect.source; + owner_in_scope(scope_id) } + // Otherwise either get an owner from the current scope or create a new one. + None => match has_context() { + Some(rt) => rt, + None => { + let owner = Rc::new(current_store().owner()); + provide_context(owner).expect("in a virtual dom") + } + }, } } diff --git a/packages/signals/src/selector.rs b/packages/signals/src/selector.rs index 5eb3fa3c9..346506ff7 100644 --- a/packages/signals/src/selector.rs +++ b/packages/signals/src/selector.rs @@ -74,6 +74,7 @@ pub fn selector(mut f: impl FnMut() -> R + 'static) -> ReadOnlySig inner: CopyValue::invalid(), }; let effect = Effect { + source: current_scope_id().expect("in a virtual dom"), callback: CopyValue::invalid(), }; From f3e7f042b42c461d88fe7bfeae880529931ef1c9 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Sat, 26 Aug 2023 14:53:39 -0500 Subject: [PATCH 2/2] fix reading signals outside of the vdom --- packages/signals/src/effect.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/signals/src/effect.rs b/packages/signals/src/effect.rs index 1a42c227f..9a54188d9 100644 --- a/packages/signals/src/effect.rs +++ b/packages/signals/src/effect.rs @@ -18,7 +18,8 @@ pub(crate) fn get_effect_stack() -> EffectStack { Some(rt) => rt, None => { let store = EffectStack::default(); - provide_root_context(store).expect("in a virtual dom") + provide_root_context(store.clone()); + store } } }