Deduplicate reactive scope updates/Reset subscriptions on reruns/fix 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
This commit is contained in:
Evan Almloff authored and GitHub committed 2024-06-18 18:49:25 -07:00
1 parent 24d247dc85
commit b6dc2a2230
18 files changed
+459 -250

No files matched your search

+1
View File
@@ -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]
@@ -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) };
}
@@ -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 {
@@ -33,7 +38,6 @@ fn values_memoize_in_place() {
},
children: count() / 2
}
TakesSignal { sig: count(), children: count() / 2 }
}
}
@@ -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
@@ -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