Skip to content

Commit

Permalink
Deduplicate reactive scope updates/Reset subscriptions on reruns/fix …
Browse files Browse the repository at this point in the history
…use memo double update (#2506)

* deduplicate effect updates

* only subscribe to signals read in the current run of reactive scopes

* subscribe to memo reads after recomputing the value
  • Loading branch information
ealmloff committed Jun 19, 2024
1 parent 24d247d commit b6dc2a2
Show file tree
Hide file tree
Showing 18 changed files with 459 additions and 250 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/core-macro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ prettyplease = "0.2.15"
[dev-dependencies]
dioxus = { workspace = true }
rustversion = "1.0"
tokio = { workspace = true, features = ["full", "time"] }
trybuild = "1.0"

[features]
Expand Down
23 changes: 16 additions & 7 deletions packages/core-macro/tests/values_memoize_in_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use dioxus::prelude::*;
use dioxus_core::ElementId;
use std::rc::Rc;

#[test]
fn values_memoize_in_place() {
#[tokio::test]
async fn values_memoize_in_place() {
thread_local! {
static DROP_COUNT: std::cell::RefCell<usize> = const { std::cell::RefCell::new(0) };
}
Expand All @@ -20,9 +20,14 @@ fn values_memoize_in_place() {
let mut count = use_signal(|| 0);
let x = CountsDrop;

if generation() < 15 {
count += 1;
}
use_hook(|| {
spawn(async move {
for _ in 0..15 {
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
count += 1;
}
});
});

rsx! {
TakesEventHandler {
Expand All @@ -33,7 +38,6 @@ fn values_memoize_in_place() {
},
children: count() / 2
}
TakesSignal { sig: count(), children: count() / 2 }
}
}

Expand All @@ -50,12 +54,16 @@ fn values_memoize_in_place() {
ElementId(1),
true,
);
tokio::select! {
_ = tokio::time::sleep(std::time::Duration::from_millis(20)) => {},
_ = dom.wait_for_work() => {}
}
dom.render_immediate(&mut dioxus_core::NoOpMutations);
}
dom.render_immediate(&mut dioxus_core::NoOpMutations);
// As we rerun the app, the drop count should be 15 one for each render of the app component
let drop_count = DROP_COUNT.with(|c| *c.borrow());
assert_eq!(drop_count, 15);
assert_eq!(drop_count, 16);
}

// We move over event handlers in place. Make sure we do that in a way that doesn't destroy the original event handler
Expand Down Expand Up @@ -98,6 +106,7 @@ fn cloning_event_handler_components_work() {

#[component]
fn TakesEventHandler(click: EventHandler<usize>, children: usize) -> Element {
println!("children is{children}");
let first_render_click = use_hook(move || click);
if generation() > 0 {
// Make sure the event handler is memoized in place and never gets dropped
Expand Down
File renamed without changes.
10 changes: 2 additions & 8 deletions packages/core/src/generational_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::{

use generational_box::{AnyStorage, Owner, SyncStorage, UnsyncStorage};

use crate::{innerlude::current_scope_id, ScopeId};
use crate::{innerlude::current_scope_id, Runtime, ScopeId};

/// Run a closure with the given owner.
///
Expand Down Expand Up @@ -91,12 +91,6 @@ pub fn current_owner<S: AnyStorage>() -> Owner<S> {
impl ScopeId {
/// Get the owner for the current scope.
pub fn owner<S: AnyStorage>(self) -> Owner<S> {
match self.has_context() {
Some(rt) => rt,
None => {
let owner = S::owner();
self.provide_context(owner)
}
}
Runtime::with_scope(self, |cx| cx.owner::<S>()).expect("to be in a dioxus runtime")
}
}
6 changes: 4 additions & 2 deletions packages/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ mod global_context;
mod mutations;
mod nodes;
mod properties;
mod reactive_context;
mod render_signal;
mod runtime;
mod scheduler;
Expand Down Expand Up @@ -42,6 +43,7 @@ pub(crate) mod innerlude {
pub use crate::mutations::*;
pub use crate::nodes::*;
pub use crate::properties::*;
pub use crate::reactive_context::*;
pub use crate::runtime::{Runtime, RuntimeGuard};
pub use crate::scheduler::*;
pub use crate::scopes::*;
Expand Down Expand Up @@ -79,7 +81,7 @@ pub mod prelude {
use_hook_with_cleanup, wait_for_next_render, with_owner, AnyValue, Attribute, Callback,
Component, ComponentFunction, Element, ErrorBoundary, Event, EventHandler, Fragment,
HasAttributes, IntoAttributeValue, IntoDynNode, OptionStringFromMarker, Properties,
Runtime, RuntimeGuard, ScopeId, ScopeState, SuperFrom, SuperInto, Task, Template,
TemplateAttribute, TemplateNode, Throw, VNode, VNodeInner, VirtualDom,
ReactiveContext, Runtime, RuntimeGuard, ScopeId, ScopeState, SuperFrom, SuperInto, Task,
Template, TemplateAttribute, TemplateNode, Throw, VNode, VNodeInner, VirtualDom,
};
}
Loading

0 comments on commit b6dc2a2

Please sign in to comment.