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