Skip to main content

leptos_use/
watch_debounced.rs

1use crate::{WatchOptions, utils::DebounceOptions, watch_with_options};
2use default_struct_builder::DefaultBuilder;
3use leptos::prelude::*;
4
5/// A debounced version of [`watch`].
6///
7/// ## Demo
8///
9/// [Link to Demo](https://github.com/Synphonyte/leptos-use/tree/main/examples/watch_debounced)
10///
11/// ## Usage
12///
13/// ```
14/// # use leptos::prelude::*;
15/// # use leptos::logging::log;
16/// # use leptos_use::watch_debounced;
17/// #
18/// # pub fn Demo() -> impl IntoView {
19/// #     let (source, set_source) = signal(0);
20/// #
21/// watch_debounced(
22///     move || source.get(),
23///     move |_, _, _| {
24///         log!("changed!");
25///     },
26///     500.0,
27/// );
28///
29/// #    view! { }
30/// # }
31/// ```
32///
33/// This really is only shorthand shorthand for `watch_with_options(deps, callback, WatchOptions::default().debounce(ms))`.
34///
35/// Please note that if the current component is cleaned up before the debounced callback is called, the debounced callback will not be called.
36///
37/// There's also [`watch_debounced_with_options`] where you can specify the other watch options (except `filter`).
38///
39/// ```
40/// # use leptos::prelude::*;
41/// # use leptos::logging::log;
42/// # use leptos_use::{watch_debounced_with_options, WatchDebouncedOptions};
43/// #
44/// # pub fn Demo() -> impl IntoView {
45/// #     let (source, set_source) = signal(0);
46/// #
47/// watch_debounced_with_options(
48///     move || source.get(),
49///     move |_, _, _| {
50///         log!("changed!");
51///     },
52///     500.0,
53///     WatchDebouncedOptions::default().max_wait(Some(1000.0)),
54/// );
55///
56/// #    view! { }
57/// # }
58/// ```
59///
60/// ## Recommended Reading
61///
62/// - [**Debounce vs Throttle**: Definitive Visual Guide](https://redd.one/blog/debounce-vs-throttle)
63/// - [Debouncing and Throttling Explained Through Examples](https://css-tricks.com/debouncing-throttling-explained-examples/)
64///
65/// ## Server-Side Rendering
66///
67/// > Make sure you follow the [instructions in Server-Side Rendering](https://leptos-use.rs/server_side_rendering.html).
68///
69/// On the server the callback
70/// will never be called except if you set `immediate` to `true` in which case the callback will be
71/// called exactly once.
72///
73/// ## See also
74///
75/// * `leptos::watch`
76/// * [`fn@crate::watch_throttled`]
77pub fn watch_debounced<W, T, DFn, CFn>(
78    deps: DFn,
79    callback: CFn,
80    ms: f64,
81) -> impl Fn() + Clone + Send + Sync
82where
83    DFn: Fn() -> W + 'static,
84    CFn: Fn(&W, Option<&W>, Option<T>) -> T + Clone + 'static,
85    W: Clone + 'static,
86    T: Clone + 'static,
87{
88    watch_with_options(deps, callback, WatchOptions::default().debounce(ms))
89}
90
91/// Version of `watch_debounced` that accepts `WatchDebouncedOptions`.
92/// See [`watch_debounced`] for how to use.
93pub fn watch_debounced_with_options<W, T, DFn, CFn>(
94    deps: DFn,
95    callback: CFn,
96    ms: f64,
97    options: WatchDebouncedOptions,
98) -> impl Fn() + Clone + Send + Sync
99where
100    DFn: Fn() -> W + 'static,
101    CFn: Fn(&W, Option<&W>, Option<T>) -> T + Clone + 'static,
102    W: Clone + 'static,
103    T: Clone + 'static,
104{
105    watch_with_options(
106        deps,
107        callback,
108        WatchOptions::default()
109            .debounce_with_options(ms, DebounceOptions::default().max_wait(options.max_wait))
110            .immediate(options.immediate),
111    )
112}
113
114/// Options for [`watch_debounced_with_options`].
115#[derive(DefaultBuilder, Default)]
116pub struct WatchDebouncedOptions {
117    /// If `immediate` is false, the `callback` will not run immediately but only after
118    /// the first change is detected of any signal that is accessed in `deps`.
119    /// Defaults to `false`.
120    immediate: bool,
121
122    /// The maximum time allowed to be delayed before the callback invoked.
123    /// In milliseconds.
124    /// Same as [`DebounceOptions::max_wait`]
125    #[builder(into)]
126    pub max_wait: Signal<Option<f64>>,
127}