yew_hooks/hooks/use_debounce.rs
1use yew::prelude::*;
2
3use super::{use_timeout, UseTimeoutHandle};
4
5/// State handle for the [`use_debounce`] hook.
6pub struct UseDebounceHandle {
7 inner: UseTimeoutHandle,
8}
9
10impl UseDebounceHandle {
11 /// Run the debounce.
12 pub fn run(&self) {
13 self.inner.reset();
14 }
15
16 /// Cancel the debounce.
17 pub fn cancel(&self) {
18 self.inner.cancel();
19 }
20}
21
22impl Clone for UseDebounceHandle {
23 fn clone(&self) -> Self {
24 Self {
25 inner: self.inner.clone(),
26 }
27 }
28}
29
30/// A hook that delays invoking a function until after wait milliseconds have elapsed
31/// since the last time the debounced function was invoked.
32///
33/// # Example
34///
35/// ```rust
36/// # use web_sys::HtmlInputElement;
37/// # use yew::prelude::*;
38/// #
39/// use yew_hooks::prelude::*;
40///
41/// #[function_component(Debounce)]
42/// fn debounce() -> Html {
43/// let status = use_state(|| "Typing stopped".to_string());
44/// let value = use_state(|| "".to_string());
45/// let debounced_value = use_state(|| "".to_string());
46///
47/// let debounce = {
48/// let value = value.clone();
49/// let status = status.clone();
50/// let debounced_value = debounced_value.clone();
51/// use_debounce(
52/// move || {
53/// debounced_value.set((*value).clone());
54/// status.set("Typing stopped".to_string());
55/// },
56/// 2000,
57/// )
58/// };
59///
60/// let oninput = {
61/// let status = status.clone();
62/// let value = value.clone();
63/// let debounce = debounce.clone();
64/// Callback::from(move |e: InputEvent| {
65/// let input: HtmlInputElement = e.target_unchecked_into();
66/// value.set(input.value());
67/// status.set("Waiting for typing to stop...".to_string());
68/// debounce.run();
69/// })
70/// };
71///
72/// let onclick = { Callback::from(move |_| debounce.cancel()) };
73///
74/// html! {
75/// <>
76/// <input type="text" value={(*value).clone()} placeholder="Debounced input" {oninput}/>
77/// <button {onclick}>{ "Cancel debounce" }</button>
78/// <p>{&*status}</p>
79/// <p>
80/// <b>{ "Value: " }</b> {&*value}
81/// </p>
82/// <p>
83/// <b>{ "Debounced value: " }</b> {&*debounced_value}
84/// </p>
85/// </>
86/// }
87/// }
88/// ```
89#[hook]
90pub fn use_debounce<Callback>(callback: Callback, millis: u32) -> UseDebounceHandle
91where
92 Callback: FnOnce() + 'static,
93{
94 let inner = use_timeout(callback, millis);
95
96 UseDebounceHandle { inner }
97}