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

+15 -2
View File
@@ -1,5 +1,6 @@
use std::{cell::Cell, rc::Rc};
use dioxus_core::prelude::*;
use dioxus_signals::ReactiveContext;
use futures_util::StreamExt;
use crate::use_callback;
@@ -15,12 +16,24 @@ pub fn use_effect(callback: impl FnMut() + 'static) -> Effect {
use_hook(|| {
// Inside the effect, we track any reads so that we can rerun the effect if a value the effect reads changes
let (rc, mut changed) = ReactiveContext::new_with_origin(location);
// Deduplicate queued effects
let effect_queued = Rc::new(Cell::new(false));
// Spawn a task that will run the effect when:
// 1) The component is first run
// 2) The effect is rerun due to an async read at any time
// 3) The effect is rerun in the same tick that the component is rerun: we need to wait for the component to rerun before we can run the effect again
let queue_effect_for_next_render = move || {
queue_effect(move || rc.run_in(&*callback));
if effect_queued.get() {
return;
}
effect_queued.set(true);
let effect_queued = effect_queued.clone();
queue_effect(move || {
rc.reset_and_run_in(&*callback);
effect_queued.set(false);
});
};
queue_effect_for_next_render();
+1 -1
View File
@@ -30,7 +30,7 @@ where
let cb = use_callback(move || {
// Create the user's task
let fut = rc.run_in(&mut future);
let fut = rc.reset_and_run_in(&mut future);
// Spawn a wrapper task that polls the inner future and watch its dependencies
spawn(async move {