sycamore_reactive/
utils.rs1use crate::*;
4
5pub trait Trackable {
9 fn _track(&self);
11}
12
13impl<T> Trackable for Signal<T> {
14 fn _track(&self) {
15 self.track();
16 }
17}
18
19impl<T> Trackable for ReadSignal<T> {
20 fn _track(&self) {
21 self.track();
22 }
23}
24
25impl<T: Into<Self>> Trackable for MaybeDyn<T> {
26 fn _track(&self) {
27 match self {
28 MaybeDyn::Static(_) => {}
29 MaybeDyn::Signal(signal) => signal.track(),
30 MaybeDyn::Derived(f) => f()._track(),
31 }
32 }
33}
34
35macro_rules! impl_trackable_deps_for_tuple {
36 ($($T:tt),*) => {
37 paste::paste! {
38 impl<$($T,)*> Trackable for ($($T,)*)
39 where
40 $($T: Trackable,)*
41 {
42 fn _track(&self) {
43 let ($([<$T:lower>],)*) = self;
44 $(
45 [<$T:lower>]._track();
46 )*
47 }
48 }
49 }
50 }
51}
52
53impl_trackable_deps_for_tuple!(A);
54impl_trackable_deps_for_tuple!(A, B);
55impl_trackable_deps_for_tuple!(A, B, C);
56impl_trackable_deps_for_tuple!(A, B, C, D);
57impl_trackable_deps_for_tuple!(A, B, C, D, E);
58impl_trackable_deps_for_tuple!(A, B, C, D, E, F);
59impl_trackable_deps_for_tuple!(A, B, C, D, E, F, G);
60impl_trackable_deps_for_tuple!(A, B, C, D, E, F, G, H);
61impl_trackable_deps_for_tuple!(A, B, C, D, E, F, G, H, I);
62impl_trackable_deps_for_tuple!(A, B, C, D, E, F, G, H, I, J);
63impl_trackable_deps_for_tuple!(A, B, C, D, E, F, G, H, I, J, K);
64impl_trackable_deps_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
65
66pub fn on<T>(
90 deps: impl Trackable + 'static,
91 mut f: impl FnMut() -> T + 'static,
92) -> impl FnMut() -> T + 'static {
93 move || {
94 deps._track();
95 untrack(&mut f)
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn on_untracks_callback() {
105 let _ = create_root(move || {
106 let trigger1 = create_signal(());
107 let trigger2 = create_signal(());
108
109 let mut counter = create_signal(0);
110 create_effect(on(trigger1, move || {
111 trigger2.track();
113 counter += 1;
114 }));
115
116 assert_eq!(counter.get(), 1);
117 trigger1.set(());
118 assert_eq!(counter.get(), 2);
119 trigger2.set(());
120 assert_eq!(counter.get(), 2);
121 });
122 }
123}