rue_core/reactive/
computed.rs1use std::cell::RefCell;
2use std::rc::Rc;
3use crate::reactive::context;
4
5pub struct Computed<T: Clone> {
9 value: Rc<RefCell<T>>,
10 dirty: Rc<RefCell<bool>>,
11 compute_fn: Rc<dyn Fn() -> T>,
12 effect_id: usize,
13}
14
15impl<T: Clone + 'static> Computed<T> {
16 pub fn new<F: Fn() -> T + 'static>(f: F) -> Self {
18 let compute_fn: Rc<dyn Fn() -> T> = Rc::new(f);
19 let initial = (compute_fn)();
20 let value = Rc::new(RefCell::new(initial));
21 let dirty = Rc::new(RefCell::new(true));
22
23 let value_clone = value.clone();
24 let dirty_clone = dirty.clone();
25 let compute_clone = compute_fn.clone();
26
27 let effect_id = context::run_effect(Box::new(move || {
28 let result = (compute_clone)();
30 *value_clone.borrow_mut() = result;
31 *dirty_clone.borrow_mut() = false;
32 }));
33
34 let compute_for_effect = compute_fn.clone();
36 context::track_effect(effect_id, move || {
37 let _ = (compute_for_effect)();
38 });
39
40 Computed {
41 value,
42 dirty,
43 compute_fn,
44 effect_id,
45 }
46 }
47
48 pub fn get(&self) -> std::cell::Ref<'_, T> {
50 context::track_signal(self.effect_id);
51 if *self.dirty.borrow() {
52 let result = (self.compute_fn)();
53 *self.value.borrow_mut() = result;
54 *self.dirty.borrow_mut() = false;
55 }
56 self.value.borrow()
57 }
58}
59
60pub fn computed<T: Clone + 'static, F: Fn() -> T + 'static>(f: F) -> Computed<T> {
62 Computed::new(f)
63}