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::{
fc_to_builder, AnyValue, Attribute, AttributeValue, BorrowedAttributeValue, CapturedError,
Component, DynamicNode, Element, ElementId, Event, Fragment, IntoDynNode, LazyNodes, Mutation,
Mutations, Properties, RenderReturn, Scope, ScopeId, ScopeState, Scoped, TaskId, Template,
TemplateAttribute, TemplateNode, VComponent, VNode, VPlaceholder, VText, VirtualDom,
fc_to_builder, vdom_is_rendering, AnyValue, Attribute, AttributeValue, BorrowedAttributeValue,
CapturedError, Component, DynamicNode, Element, ElementId, Event, Fragment, IntoDynNode,
LazyNodes, Mutation, Mutations, Properties, RenderReturn, Scope, ScopeId, ScopeState, Scoped,
TaskId, Template, TemplateAttribute, TemplateNode, VComponent, VNode, VPlaceholder, VText,
VirtualDom,
};
/// 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 std::rc::Rc;
@ -47,6 +47,7 @@ pub struct Runtime {
// We use this to track the current scope
pub(crate) scope_stack: RefCell<Vec<ScopeId>>,
pub(crate) rendering: Cell<bool>,
}
impl Runtime {
@ -57,6 +58,8 @@ impl Runtime {
scope_contexts: Default::default(),
scope_stack: Default::default(),
rendering: Cell::new(true),
});
runtime
}

View file

@ -20,6 +20,7 @@ impl VirtualDom {
// update the scope stack
self.runtime.scope_stack.borrow_mut().push(task.scope);
self.runtime.rendering.set(false);
// If the task completes...
if task.task.borrow_mut().as_mut().poll(&mut cx).is_ready() {
@ -33,5 +34,6 @@ impl VirtualDom {
// Remove the scope from the stack
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()
}
#[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
pub fn consume_context<T: 'static + Clone>() -> Option<T> {
with_current_scope(|cx| cx.consume_context::<T>()).flatten()

View file

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

View file

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