Skip to content

Commit 702864a

Browse files
committed
docs(cache): Add examples of using Effect, Memo and Signal in Struct
1 parent 44d7b60 commit 702864a

File tree

3 files changed

+229
-0
lines changed

3 files changed

+229
-0
lines changed

cache/src/effect.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,65 @@ use crate::effect_stack::{effect_peak, effect_pop, effect_push};
1515
/// - Like a callback: wraps a closure and runs it.
1616
/// - Adds tracking: automatically re-runs when dependent signals change.
1717
/// - Runs once immediately at creation.
18+
///
19+
/// # Examples
20+
///
21+
/// ## Basic usage
22+
/// ```
23+
/// use std::{cell::Cell, rc::Rc};
24+
/// use reactive_cache::Effect;
25+
///
26+
/// let counter = Rc::new(Cell::new(0));
27+
/// let c_clone = counter.clone();
28+
///
29+
/// let effect = Effect::new(move || {
30+
/// // This closure runs immediately
31+
/// c_clone.set(c_clone.get() + 1);
32+
/// });
33+
///
34+
/// assert_eq!(counter.get(), 1);
35+
/// ```
36+
///
37+
/// ## Using inside a struct
38+
/// ```
39+
/// use std::{rc::Rc, cell::Cell};
40+
/// use reactive_cache::{Signal, Memo, Effect};
41+
///
42+
/// struct ViewModel {
43+
/// counter: Rc<Signal<i32>>,
44+
/// double: Rc<Memo<i32>>,
45+
/// effect: Rc<Effect>,
46+
/// run_count: Rc<Cell<u32>>,
47+
/// }
48+
///
49+
/// let counter = Rc::new(Signal::new(Some(1)));
50+
/// let double = Memo::new({
51+
/// let counter = counter.clone();
52+
/// move || *counter.get() * 2
53+
/// });
54+
///
55+
/// let run_count = Rc::new(Cell::new(0));
56+
/// let run_count_clone = run_count.clone();
57+
///
58+
/// let effect = Effect::new({
59+
/// let double = double.clone();
60+
/// move || {
61+
/// run_count_clone.set(run_count_clone.get() + 1);
62+
/// let _ = double.get();
63+
/// }
64+
/// });
65+
///
66+
/// let vm = ViewModel {
67+
/// counter: counter.clone(),
68+
/// double: double.clone(),
69+
/// effect: effect,
70+
/// run_count: run_count.clone(),
71+
/// };
72+
///
73+
/// assert_eq!(run_count.get(), 1);
74+
/// vm.counter.set(4);
75+
/// assert_eq!(run_count.get(), 2);
76+
/// ```
1877
pub struct Effect {
1978
f: Box<dyn Fn()>,
2079
}
@@ -28,6 +87,7 @@ impl Effect {
2887
///
2988
/// # Examples
3089
///
90+
/// ## Basic usage
3191
/// ```
3292
/// use std::{cell::Cell, rc::Rc};
3393
/// use reactive_cache::Effect;
@@ -42,6 +102,36 @@ impl Effect {
42102
///
43103
/// assert_eq!(counter.get(), 1);
44104
/// ```
105+
///
106+
/// ## Using inside a struct
107+
/// ```
108+
/// use std::rc::Rc;
109+
/// use reactive_cache::{Signal, Memo, Effect};
110+
///
111+
/// struct ViewModel {
112+
/// counter: Rc<Signal<i32>>,
113+
/// double: Rc<Memo<i32>>,
114+
/// effect: Rc<Effect>,
115+
/// }
116+
///
117+
/// let counter = Rc::new(Signal::new(Some(1)));
118+
/// let double = Memo::new({
119+
/// let counter = counter.clone();
120+
/// move || *counter.get() * 2
121+
/// });
122+
///
123+
/// let vm = ViewModel {
124+
/// counter: counter.clone(),
125+
/// double: double.clone(),
126+
/// effect: Effect::new({
127+
/// let double = double.clone();
128+
/// move || println!("Double is {}", double.get())
129+
/// }),
130+
/// };
131+
///
132+
/// counter.set(3);
133+
/// assert_eq!(double.get(), 6);
134+
/// ```
45135
#[allow(clippy::new_ret_no_self)]
46136
pub fn new(f: impl Fn() + 'static) -> Rc<Effect> {
47137
let e: Rc<Effect> = Rc::new(Effect { f: Box::new(f) });

cache/src/memo.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,49 @@ use crate::{IObservable, memo_stack, store_in_cache, touch};
1818
/// # Type Parameters
1919
///
2020
/// - `T`: The result type of the computation. Must implement `Clone`.
21+
///
22+
/// # Examples
23+
///
24+
/// ## Basic usage
25+
/// ```
26+
/// use std::rc::Rc;
27+
/// use reactive_cache::{Signal, Memo};
28+
///
29+
/// let counter = Rc::new(Signal::new(Some(1)));
30+
/// let double = {
31+
/// let counter = Rc::clone(&counter);
32+
/// Memo::new({
33+
/// let counter = Rc::new(counter);
34+
/// move || *counter.get() * 2
35+
/// })
36+
/// };
37+
///
38+
/// assert_eq!(double.get(), 2);
39+
/// counter.set(3);
40+
/// assert_eq!(double.get(), 6);
41+
/// ```
42+
///
43+
/// ## Using inside a struct
44+
/// ```
45+
/// use std::rc::Rc;
46+
/// use reactive_cache::{Signal, Memo};
47+
///
48+
/// struct ViewModel {
49+
/// counter: Rc<Signal<i32>>,
50+
/// double: Rc<Memo<i32>>,
51+
/// }
52+
///
53+
/// let counter = Rc::new(Signal::new(Some(1)));
54+
/// let double = Memo::new({
55+
/// let counter = counter.clone();
56+
/// move || *counter.get() * 2
57+
/// });
58+
///
59+
/// let vm = ViewModel { counter, double };
60+
/// assert_eq!(vm.double.get(), 2);
61+
/// vm.counter.set(4);
62+
/// assert_eq!(vm.double.get(), 8);
63+
/// ```
2164
pub struct Memo<T> {
2265
f: Box<dyn Fn() -> T>,
2366
dependents: RefCell<Vec<Weak<dyn IMemo>>>,
@@ -35,12 +78,49 @@ impl<T> Memo<T> {
3578
///
3679
/// # Examples
3780
///
81+
/// Basic usage:
3882
/// ```
3983
/// use reactive_cache::Memo;
4084
///
4185
/// let memo = Memo::new(|| 10);
4286
/// assert_eq!(memo.get(), 10);
4387
/// ```
88+
///
89+
/// Using inside a struct:
90+
/// ```
91+
/// use std::rc::Rc;
92+
///
93+
/// use reactive_cache::{Signal, Memo};
94+
///
95+
/// struct ViewModel {
96+
/// a: Rc<Signal<i32>>,
97+
/// b: Rc<Signal<i32>>,
98+
/// sum: Rc<Memo<i32>>,
99+
/// }
100+
///
101+
/// // Construct signals
102+
/// let a = Rc::new(Signal::new(Some(2)));
103+
/// let b = Rc::new(Signal::new(Some(3)));
104+
///
105+
/// // Construct a memo depending on `a` and `b`
106+
/// let sum = {
107+
/// let a = a.clone();
108+
/// let b = b.clone();
109+
/// Memo::new(move || {
110+
/// // `Signal::get()` will register dependencies automatically
111+
/// *a.get() + *b.get()
112+
/// })
113+
/// };
114+
///
115+
/// let vm = ViewModel { a, b, sum };
116+
///
117+
/// // Initial computation
118+
/// assert_eq!(vm.sum.get(), 5);
119+
///
120+
/// // Update a signal → memo recomputes
121+
/// vm.a.set(10);
122+
/// assert_eq!(vm.sum.get(), 13);
123+
/// ```
44124
pub fn new(f: impl Fn() -> T + 'static) -> Rc<Self>
45125
where
46126
T: 'static,

cache/src/signal.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,39 @@ use crate::{Effect, IMemo, IObservable, effect_stack::EffectStackEntry};
2020
/// # Type Parameters
2121
///
2222
/// - `T`: The type of the value stored in the signal. Must implement `Eq + Default`.
23+
///
24+
/// # Examples
25+
///
26+
/// ## Basic usage
27+
/// ```
28+
/// use std::rc::Rc;
29+
/// use std::cell::Cell;
30+
/// use reactive_cache::Signal;
31+
///
32+
/// let signal = Signal::new(Some(10));
33+
/// assert_eq!(*signal.get(), 10);
34+
///
35+
/// let default_signal: Signal<i32> = Signal::new(None);
36+
/// assert_eq!(*default_signal.get(), 0);
37+
/// ```
38+
///
39+
/// ## Using inside a struct
40+
/// ```
41+
/// use std::{rc::Rc, cell::Cell};
42+
/// use reactive_cache::Signal;
43+
///
44+
/// struct ViewModel {
45+
/// counter: Signal<i32>,
46+
/// sum: Signal<i32>,
47+
/// }
48+
///
49+
/// let counter = Signal::new(Some(5));
50+
/// let sum = Signal::new(None);
51+
/// let vm = ViewModel { counter, sum };
52+
///
53+
/// assert_eq!(*vm.counter.get(), 5);
54+
/// assert_eq!(*vm.sum.get(), 0);
55+
/// ```
2356
pub struct Signal<T> {
2457
value: RefCell<T>,
2558
dependents: RefCell<Vec<Weak<dyn IMemo>>>,
@@ -63,6 +96,7 @@ impl<T> Signal<T> {
6396
///
6497
/// # Examples
6598
///
99+
/// Basic usage:
66100
/// ```
67101
/// use reactive_cache::Signal;
68102
///
@@ -72,6 +106,31 @@ impl<T> Signal<T> {
72106
/// let default_signal: Signal<i32> = Signal::new(None);
73107
/// assert_eq!(*default_signal.get(), 0);
74108
/// ```
109+
///
110+
/// Using inside a struct:
111+
/// ```
112+
/// use reactive_cache::Signal;
113+
///
114+
/// struct ViewModel {
115+
/// counter: Signal<i32>,
116+
/// name: Signal<String>,
117+
/// }
118+
///
119+
/// let vm = ViewModel {
120+
/// counter: Signal::new(Some(0)),
121+
/// name: Signal::new(Some("Alice".to_string())),
122+
/// };
123+
///
124+
/// assert_eq!(*vm.counter.get(), 0);
125+
/// assert_eq!(*vm.name.get(), "Alice");
126+
///
127+
/// // Update values
128+
/// assert!(vm.counter.set(1));
129+
/// assert!(vm.name.set("Bob".into()));
130+
///
131+
/// assert_eq!(*vm.counter.get(), 1);
132+
/// assert_eq!(*vm.name.get(), "Bob");
133+
/// ```
75134
pub fn new(value: Option<T>) -> Self
76135
where
77136
T: Default,

0 commit comments

Comments
 (0)