diff --git a/packages/signals/src/effect.rs b/packages/signals/src/effect.rs index 0685938a0..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 } } } @@ -54,6 +55,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 +75,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(), };