sycamore_reactive/
utils.rs

1//! A few handy utilities.
2
3use crate::*;
4
5/// A trait that is implemented for reactive data that can be tracked, such as [`Signal`].
6///
7/// Also implemented for tuples containing `Trackable`s.
8pub trait Trackable {
9    /// Track the data reactively.
10    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
25macro_rules! impl_trackable_deps_for_tuple {
26    ($($T:tt),*) => {
27        paste::paste! {
28            impl<$($T,)*> Trackable for ($($T,)*)
29            where
30                $($T: Trackable,)*
31            {
32                fn _track(&self) {
33                    let ($([<$T:lower>],)*) = self;
34                    $(
35                        [<$T:lower>]._track();
36                    )*
37                }
38            }
39        }
40    }
41}
42
43impl_trackable_deps_for_tuple!(A);
44impl_trackable_deps_for_tuple!(A, B);
45impl_trackable_deps_for_tuple!(A, B, C);
46impl_trackable_deps_for_tuple!(A, B, C, D);
47impl_trackable_deps_for_tuple!(A, B, C, D, E);
48impl_trackable_deps_for_tuple!(A, B, C, D, E, F);
49impl_trackable_deps_for_tuple!(A, B, C, D, E, F, G);
50impl_trackable_deps_for_tuple!(A, B, C, D, E, F, G, H);
51impl_trackable_deps_for_tuple!(A, B, C, D, E, F, G, H, I);
52impl_trackable_deps_for_tuple!(A, B, C, D, E, F, G, H, I, J);
53impl_trackable_deps_for_tuple!(A, B, C, D, E, F, G, H, I, J, K);
54impl_trackable_deps_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
55
56/// A helper function for making dependencies explicit.
57///
58/// # Params
59/// * `deps` - A list of signals/memos that are tracked. This can be a single signal or it can be a
60///   tuple of signals.
61/// * `f` - The callback function.
62///
63/// # Example
64/// ```
65/// # use sycamore_reactive::*;
66/// # create_root(|| {
67/// let state = create_signal(0);
68///
69/// create_effect(on(state, move || {
70///     println!("State changed. New state value = {}", state.get());
71/// }));
72/// // Prints "State changed. New state value = 0"
73///
74/// state.set(1);
75/// // Prints "State changed. New state value = 1"
76/// # });
77/// ```
78pub fn on<T>(
79    deps: impl Trackable + 'static,
80    mut f: impl FnMut() -> T + 'static,
81) -> impl FnMut() -> T + 'static {
82    move || {
83        deps._track();
84        f()
85    }
86}