don't subscribe in tasks or event handlers

This commit is contained in:
Evan Almloff 2023-08-07 17:55:29 -07:00
parent 4447709ac8
commit 0c17bdb737
6 changed files with 35 additions and 16 deletions

View file

@ -73,10 +73,11 @@ pub(crate) mod innerlude {
} }
pub use crate::innerlude::{ pub use crate::innerlude::{
fc_to_builder, AnyValue, Attribute, AttributeValue, BorrowedAttributeValue, CapturedError, fc_to_builder, vdom_is_rendering, AnyValue, Attribute, AttributeValue, BorrowedAttributeValue,
Component, DynamicNode, Element, ElementId, Event, Fragment, IntoDynNode, LazyNodes, Mutation, CapturedError, Component, DynamicNode, Element, ElementId, Event, Fragment, IntoDynNode,
Mutations, Properties, RenderReturn, Scope, ScopeId, ScopeState, Scoped, TaskId, Template, LazyNodes, Mutation, Mutations, Properties, RenderReturn, Scope, ScopeId, ScopeState, Scoped,
TemplateAttribute, TemplateNode, VComponent, VNode, VPlaceholder, VText, VirtualDom, TaskId, Template, TemplateAttribute, TemplateNode, VComponent, VNode, VPlaceholder, VText,
VirtualDom,
}; };
/// The purpose of this module is to alleviate imports of many common types /// The purpose of this module is to alleviate imports of many common types

View file

@ -1,4 +1,4 @@
use std::cell::{Ref, RefCell}; use std::cell::{Cell, Ref, RefCell};
use crate::{innerlude::Scheduler, scope_context::ScopeContext, scopes::ScopeId}; use crate::{innerlude::Scheduler, scope_context::ScopeContext, scopes::ScopeId};
use std::rc::Rc; use std::rc::Rc;
@ -47,6 +47,7 @@ pub struct Runtime {
// We use this to track the current scope // We use this to track the current scope
pub(crate) scope_stack: RefCell<Vec<ScopeId>>, pub(crate) scope_stack: RefCell<Vec<ScopeId>>,
pub(crate) rendering: Cell<bool>,
} }
impl Runtime { impl Runtime {
@ -57,6 +58,8 @@ impl Runtime {
scope_contexts: Default::default(), scope_contexts: Default::default(),
scope_stack: Default::default(), scope_stack: Default::default(),
rendering: Cell::new(true),
}); });
runtime runtime
} }

View file

@ -20,6 +20,7 @@ impl VirtualDom {
// update the scope stack // update the scope stack
self.runtime.scope_stack.borrow_mut().push(task.scope); self.runtime.scope_stack.borrow_mut().push(task.scope);
self.runtime.rendering.set(false);
// If the task completes... // If the task completes...
if task.task.borrow_mut().as_mut().poll(&mut cx).is_ready() { if task.task.borrow_mut().as_mut().poll(&mut cx).is_ready() {
@ -33,5 +34,6 @@ impl VirtualDom {
// Remove the scope from the stack // Remove the scope from the stack
self.runtime.scope_stack.borrow_mut().pop(); self.runtime.scope_stack.borrow_mut().pop();
self.runtime.rendering.set(true);
} }
} }

View file

@ -263,6 +263,12 @@ pub fn current_scope_id() -> Option<ScopeId> {
with_runtime(|rt| rt.current_scope_id()).flatten() with_runtime(|rt| rt.current_scope_id()).flatten()
} }
#[doc(hidden)]
/// Check if the virtual dom is currently inside of the body of a component
pub fn vdom_is_rendering() -> bool {
with_runtime(|rt| rt.rendering.get()).unwrap_or_default()
}
/// Consume context from the current scope /// Consume context from the current scope
pub fn consume_context<T: 'static + Clone>() -> Option<T> { pub fn consume_context<T: 'static + Clone>() -> Option<T> {
with_current_scope(|cx| cx.consume_context::<T>()).flatten() with_current_scope(|cx| cx.consume_context::<T>()).flatten()

View file

@ -392,10 +392,12 @@ impl VirtualDom {
if let AttributeValue::Listener(listener) = listener { if let AttributeValue::Listener(listener) = listener {
let origin = el_ref.scope; let origin = el_ref.scope;
self.runtime.scope_stack.borrow_mut().push(origin); self.runtime.scope_stack.borrow_mut().push(origin);
self.runtime.rendering.set(false);
if let Some(cb) = listener.borrow_mut().as_deref_mut() { if let Some(cb) = listener.borrow_mut().as_deref_mut() {
cb(uievent.clone()); cb(uievent.clone());
} }
self.runtime.scope_stack.borrow_mut().pop(); self.runtime.scope_stack.borrow_mut().pop();
self.runtime.rendering.set(true);
if !uievent.propagates.get() { if !uievent.propagates.get() {
return; return;
@ -426,10 +428,12 @@ impl VirtualDom {
if let AttributeValue::Listener(listener) = &attr.value { if let AttributeValue::Listener(listener) = &attr.value {
let origin = el_ref.scope; let origin = el_ref.scope;
self.runtime.scope_stack.borrow_mut().push(origin); self.runtime.scope_stack.borrow_mut().push(origin);
self.runtime.rendering.set(false);
if let Some(cb) = listener.borrow_mut().as_deref_mut() { if let Some(cb) = listener.borrow_mut().as_deref_mut() {
cb(uievent.clone()); cb(uievent.clone());
} }
self.runtime.scope_stack.borrow_mut().pop(); self.runtime.scope_stack.borrow_mut().pop();
self.runtime.rendering.set(true);
break; break;
} }

View file

@ -109,17 +109,20 @@ impl<T: 'static> Signal<T> {
effect_subscribers.push(effect); effect_subscribers.push(effect);
} }
} else if let Some(current_scope_id) = current_scope_id() { } else if let Some(current_scope_id) = current_scope_id() {
log::trace!( // only subscribe if the vdom is rendering
"{:?} subscribed to {:?}", if dioxus_core::vdom_is_rendering() {
self.inner.value, log::trace!(
current_scope_id "{:?} subscribed to {:?}",
); self.inner.value,
let mut subscribers = inner.subscribers.borrow_mut(); current_scope_id
if !subscribers.contains(&current_scope_id) { );
subscribers.push(current_scope_id); let mut subscribers = inner.subscribers.borrow_mut();
drop(subscribers); if !subscribers.contains(&current_scope_id) {
let unsubscriber = current_unsubscriber(); subscribers.push(current_scope_id);
inner.subscribers.borrow_mut().push(unsubscriber.scope); drop(subscribers);
let unsubscriber = current_unsubscriber();
inner.subscribers.borrow_mut().push(unsubscriber.scope);
}
} }
} }
Ref::map(inner, |v| &v.value) Ref::map(inner, |v| &v.value)