yew_hooks/hooks/
use_throttle_state.rs

1use std::ops::Deref;
2use std::rc::Rc;
3
4use yew::prelude::*;
5
6use super::use_throttle;
7
8/// State handle for the [`use_throttle_state`] hook.
9pub struct UseThrottleStateHandle<T> {
10    inner: UseStateHandle<T>,
11    set: Rc<dyn Fn(T)>,
12}
13
14impl<T> UseThrottleStateHandle<T> {
15    // Set the value.
16    pub fn set(&self, value: T) {
17        (self.set)(value);
18    }
19}
20
21impl<T> Deref for UseThrottleStateHandle<T> {
22    type Target = T;
23
24    fn deref(&self) -> &Self::Target {
25        &self.inner
26    }
27}
28
29impl<T> Clone for UseThrottleStateHandle<T> {
30    fn clone(&self) -> Self {
31        Self {
32            inner: self.inner.clone(),
33            set: self.set.clone(),
34        }
35    }
36}
37
38impl<T> PartialEq for UseThrottleStateHandle<T>
39where
40    T: PartialEq,
41{
42    fn eq(&self, other: &Self) -> bool {
43        *self.inner == *other.inner
44    }
45}
46
47/// A hook that throttles updating state, the state is only updated once every `millis`.
48///
49/// # Example
50///
51/// ```rust
52/// # use yew::prelude::*;
53/// #
54/// use yew_hooks::prelude::*;
55///
56/// #[function_component(ThrottleState)]
57/// fn throttle_state() -> Html {
58///     let state = use_throttle_state(|| 0, 2000);
59///
60///     let onclick = {
61///         let state = state.clone();
62///         Callback::from(move |_| state.set(*state + 1))
63///     };
64///
65///     html! {
66///         <>
67///             <button {onclick}>{ "Click fast!" }</button>
68///             <b>{ "State: " }</b> {*state}
69///         </>
70///     }
71/// }
72/// ```
73#[hook]
74pub fn use_throttle_state<T, F>(init_fn: F, millis: u32) -> UseThrottleStateHandle<T>
75where
76    T: 'static,
77    F: FnOnce() -> T,
78{
79    let value = use_mut_ref(|| None);
80    let inner = use_state(init_fn);
81    let throttle = {
82        let value = value.clone();
83        let inner = inner.clone();
84        use_throttle(
85            move || {
86                let value = (*value.borrow_mut()).take();
87                if let Some(value) = value {
88                    inner.set(value);
89                }
90            },
91            millis,
92        )
93    };
94
95    let set = {
96        Rc::new(move |new_value: T| {
97            *value.borrow_mut() = Some(new_value);
98            throttle.run();
99        })
100    };
101
102    UseThrottleStateHandle { inner, set }
103}