melt_ui/utils/
signal.rs

1use leptos::{create_effect, untrack, RwSignal, SignalDispose, SignalWith};
2
3pub trait SignalWatch {
4    type Value;
5
6    fn watch(&self, f: impl Fn(&Self::Value) + 'static) -> Box<dyn FnOnce()>;
7}
8
9impl<T> SignalWatch for RwSignal<T> {
10    type Value = T;
11
12    /// Listens for RwSignal changes and is not executed immediately
13    ///
14    /// ## Usage
15    ///
16    /// ```rust
17    /// use leptos::*;
18    /// use melt_ui::*;
19    ///
20    /// let count = create_rw_signal(0);
21    /// let stop = count.watch(|count| {
22    ///     assert_eq!(count, &1);
23    /// });
24    ///
25    /// count.set(1); // assert_eq!(count, &1);
26    ///
27    /// stop(); // stop watching
28    ///
29    /// count.set(2); // nothing happens
30    /// ```
31    fn watch(&self, f: impl Fn(&Self::Value) + 'static) -> Box<dyn FnOnce()> {
32        let signal = *self;
33
34        let effect = create_effect(move |prev| {
35            signal.with(|value| {
36                if prev.is_some() {
37                    untrack(|| f(value));
38                }
39            });
40        });
41
42        Box::new(move || {
43            effect.dispose();
44        })
45    }
46}