Skip to content

Commit

Permalink
Allow batching within a batch (#137)
Browse files Browse the repository at this point in the history
  • Loading branch information
MinusGix authored Nov 3, 2023
1 parent 639d86b commit 2a829ed
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 6 deletions.
20 changes: 14 additions & 6 deletions reactive/src/effect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,22 @@ pub fn untrack<T>(f: impl FnOnce() -> T) -> T {
}

pub fn batch<T>(f: impl FnOnce() -> T) -> T {
RUNTIME.with(|runtime| {
runtime.batching.set(true);
let already_batching = RUNTIME.with(|runtime| {
let batching = runtime.batching.get();
if !batching {
runtime.batching.set(true);
}

batching
});

let result = f();
RUNTIME.with(|runtime| {
runtime.batching.set(false);
runtime.run_pending_effects();
});
if !already_batching {
RUNTIME.with(|runtime| {
runtime.batching.set(false);
runtime.run_pending_effects();
});
}

result
}
Expand Down
70 changes: 70 additions & 0 deletions reactive/tests/effect.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use std::{cell::Cell, rc::Rc};

use floem_reactive::{batch, create_effect, create_rw_signal};

#[test]
fn batch_simple() {
let name = create_rw_signal("John");
let age = create_rw_signal(20);

let count = Rc::new(Cell::new(0));

create_effect({
let count = count.clone();
move |_| {
name.track();
age.track();

count.set(count.get() + 1);
}
});

// The effect runs once immediately
assert_eq!(count.get(), 1);

// Setting each signal once will trigger the effect
name.set("Mary");
assert_eq!(count.get(), 2);

age.set(21);
assert_eq!(count.get(), 3);

// Batching will only update once
batch(|| {
name.set("John");
age.set(20);
});
assert_eq!(count.get(), 4);
}

#[test]
fn batch_batch() {
let name = create_rw_signal("John");
let age = create_rw_signal(20);

let count = Rc::new(Cell::new(0));

create_effect({
let count = count.clone();
move |_| {
name.track();
age.track();

count.set(count.get() + 1);
}
});

assert_eq!(count.get(), 1);

// Batching within another batch should be equivalent to batching them all together
batch(|| {
name.set("Mary");
age.set(21);
batch(|| {
name.set("John");
age.set(20);
});
});

assert_eq!(count.get(), 2);
}

0 comments on commit 2a829ed

Please sign in to comment.