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 122 123 124 125 126 127 128 129 130 131 132 133
use crate::{watch_with_options, ThrottleOptions, WatchOptions};
use default_struct_builder::DefaultBuilder;
/// A throttled version of `leptos::watch`.
///
/// ## Demo
///
/// [Link to Demo](https://github.com/Synphonyte/leptos-use/tree/main/examples/watch_throttled)
///
/// ## Usage
///
/// ```
/// # use leptos::*;
/// # use leptos::logging::log;
/// # use leptos_use::watch_throttled;
/// #
/// # pub fn Demo() -> impl IntoView {
/// # let (source, set_source) = create_signal(0);
/// #
/// watch_throttled(
/// move || source.get(),
/// move |_, _, _| {
/// log!("changed!");
/// },
/// 500.0,
/// );
///
/// # view! { }
/// # }
/// ```
///
/// This really is only shorthand shorthand for `watch_with_options(deps, callback, WatchOptions::default().throttle(ms))`.
///
/// Please note that if the current component is cleaned up before the throttled callback is called, the throttled callback will not be called.
///
/// There's also `watch_throttled_with_options` where you can specify the other watch options (except `filter`).
///
/// ```
/// # use leptos::*;
/// # use leptos::logging::log;
/// # use leptos_use::{watch_throttled_with_options, WatchThrottledOptions};
/// #
/// # pub fn Demo() -> impl IntoView {
/// # let (source, set_source) = create_signal(0);
/// #
/// watch_throttled_with_options(
/// move || source.get(),
/// move |_, _, _| {
/// log!("changed!");
/// },
/// 500.0,
/// WatchThrottledOptions::default().leading(true).trailing(false),
/// );
///
/// # 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_debounced`]
pub fn watch_throttled<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().throttle(ms))
}
/// Version of [`fn@watch_throttled`] that accepts `WatchThrottledOptions`. See [`watch_throttled`] for how to use.
pub fn watch_throttled_with_options<W, T, DFn, CFn>(
deps: DFn,
callback: CFn,
ms: f64,
options: WatchThrottledOptions,
) -> 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()
.throttle_with_options(
ms,
ThrottleOptions::default()
.leading(options.leading)
.trailing(options.trailing),
)
.immediate(options.immediate),
)
}
/// Options for [`watch_throttled_with_options`].
#[derive(DefaultBuilder)]
pub struct WatchThrottledOptions {
/// 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,
/// Invoke on the trailing edge of the timeout. Defaults to `true`.
pub trailing: bool,
/// Invoke on the leading edge of the timeout. Defaults to `true`.
pub leading: bool,
}
impl Default for WatchThrottledOptions {
fn default() -> Self {
Self {
immediate: false,
trailing: true,
leading: true,
}
}
}