diff --git a/README.md b/README.md index b452805..942730c 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,7 @@ fn counter() -> Html { - `use_debounce` - debounces a function. - `use_debounce_effect` - debounces an effect. - `use_throttle` - throttles a function. +- `use_throttle_effect` - throttles an effect. ### Lifecycles diff --git a/crates/yew-hooks/Cargo.toml b/crates/yew-hooks/Cargo.toml index 77f54da..73601ca 100644 --- a/crates/yew-hooks/Cargo.toml +++ b/crates/yew-hooks/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yew-hooks" -version = "0.1.51" +version = "0.1.52" edition = "2018" authors = ["Jet Li "] categories = ["gui", "wasm", "web-programming"] diff --git a/crates/yew-hooks/src/hooks/mod.rs b/crates/yew-hooks/src/hooks/mod.rs index 3de6fcb..68257b7 100644 --- a/crates/yew-hooks/src/hooks/mod.rs +++ b/crates/yew-hooks/src/hooks/mod.rs @@ -39,6 +39,7 @@ mod use_size; mod use_state_ptr_eq; mod use_swipe; mod use_throttle; +mod use_throttle_effect; mod use_throttle_state; mod use_timeout; mod use_title; @@ -90,6 +91,7 @@ pub use use_size::*; pub use use_state_ptr_eq::*; pub use use_swipe::*; pub use use_throttle::*; +pub use use_throttle_effect::*; pub use use_throttle_state::*; pub use use_timeout::*; pub use use_title::*; diff --git a/crates/yew-hooks/src/hooks/use_throttle_effect.rs b/crates/yew-hooks/src/hooks/use_throttle_effect.rs new file mode 100644 index 0000000..4b65fe6 --- /dev/null +++ b/crates/yew-hooks/src/hooks/use_throttle_effect.rs @@ -0,0 +1,88 @@ +use yew::prelude::*; + +use super::{use_throttle, use_unmount}; + +/// A hook that throttles calling effect callback, it is only called once every `millis`. +/// +/// # Example +/// +/// ```rust +/// # use yew::prelude::*; +/// # +/// use yew_hooks::{use_throttle_effect, use_update}; +/// +/// #[function_component(ThrottleEffect)] +/// fn throttle_effect() -> Html { +/// let state = use_state(|| 0); +/// let update = use_update(); +/// +/// { +/// let state = state.clone(); +/// use_throttle_effect( +/// move || { +/// state.set(*state + 1); +/// }, +/// 2000, +/// ) +/// }; +/// +/// let onclick = { Callback::from(move |_| update()) }; +/// +/// html! { +/// <> +/// +/// { "State: " } {*state} +/// +/// } +/// } +/// ``` +pub fn use_throttle_effect(callback: Callback, millis: u32) +where + Callback: FnMut() + 'static, +{ + let throttle = use_throttle(callback, millis); + + { + let throttle = throttle.clone(); + use_effect(move || { + throttle.run(); + + || () + }); + } + + use_unmount(move || { + throttle.cancel(); + }); +} + +/// This hook is similar to [`use_throttle_effect`] but it accepts dependencies. +/// +/// Whenever the dependencies are changed, the throttle effect is run again. +/// To detect changes, dependencies must implement `PartialEq`. +pub fn use_throttle_effect_with_deps( + callback: Callback, + millis: u32, + deps: Dependents, +) where + Callback: FnMut() + 'static, + Dependents: PartialEq + 'static, +{ + let throttle = use_throttle(callback, millis); + + { + let throttle = throttle.clone(); + use_effect_with_deps( + move |_| { + throttle.run(); + + || () + }, + deps, + ); + } + + use_unmount(move || { + throttle.cancel(); + }); +} diff --git a/examples/yew-app/src/routes/home.rs b/examples/yew-app/src/routes/home.rs index 0a00453..a80bd39 100644 --- a/examples/yew-app/src/routes/home.rs +++ b/examples/yew-app/src/routes/home.rs @@ -44,6 +44,7 @@ pub fn home() -> Html {
  • to={AppRoute::UseDebounce} classes="app-link" >{ "use_debounce" }> { " - debounces a function." }
  • to={AppRoute::UseDebounceEffect} classes="app-link" >{ "use_debounce_effect" }> { " - debounces an effect." }
  • to={AppRoute::UseThrottle} classes="app-link" >{ "use_throttle" }> { " - throttles a function." }
  • +
  • to={AppRoute::UseThrottleEffect} classes="app-link" >{ "use_throttle_effect" }> { " - throttles an effect." }
  • { "Lifecycles" }

    diff --git a/examples/yew-app/src/routes/hooks/mod.rs b/examples/yew-app/src/routes/hooks/mod.rs index 4213e0c..3c0f003 100644 --- a/examples/yew-app/src/routes/hooks/mod.rs +++ b/examples/yew-app/src/routes/hooks/mod.rs @@ -41,6 +41,7 @@ mod use_size; mod use_state_ptr_eq; mod use_swipe; mod use_throttle; +mod use_throttle_effect; mod use_throttle_state; mod use_timeout; mod use_title; @@ -94,6 +95,7 @@ pub use use_size::*; pub use use_state_ptr_eq::*; pub use use_swipe::*; pub use use_throttle::*; +pub use use_throttle_effect::*; pub use use_throttle_state::*; pub use use_timeout::*; pub use use_title::*; diff --git a/examples/yew-app/src/routes/hooks/use_throttle_effect.rs b/examples/yew-app/src/routes/hooks/use_throttle_effect.rs new file mode 100644 index 0000000..44adb78 --- /dev/null +++ b/examples/yew-app/src/routes/hooks/use_throttle_effect.rs @@ -0,0 +1,35 @@ +use yew::prelude::*; + +use yew_hooks::{use_throttle_effect, use_update}; + +/// `use_throttle_effect` demo +#[function_component(UseThrottleEffect)] +pub fn throttle_effect() -> Html { + let state = use_state(|| 0); + let update = use_update(); + + { + let state = state.clone(); + use_throttle_effect( + move || { + state.set(*state + 1); + }, + 2000, + ) + }; + + let onclick = { Callback::from(move |_| update()) }; + + html! { +
    +
    +
    + +

    + { "State: " } {*state} +

    +
    +
    +
    + } +} diff --git a/examples/yew-app/src/routes/mod.rs b/examples/yew-app/src/routes/mod.rs index dc11825..163e654 100644 --- a/examples/yew-app/src/routes/mod.rs +++ b/examples/yew-app/src/routes/mod.rs @@ -118,6 +118,8 @@ pub enum AppRoute { UseThrottleState, #[at("/use_debounce_effect")] UseDebounceEffect, + #[at("/use_throttle_effect")] + UseThrottleEffect, #[not_found] #[at("/page-not-found")] PageNotFound, @@ -182,6 +184,7 @@ pub fn switch(routes: &AppRoute) -> Html { AppRoute::UseThrottle => html! { }, AppRoute::UseThrottleState => html! { }, AppRoute::UseDebounceEffect => html! { }, + AppRoute::UseThrottleEffect => html! { }, AppRoute::PageNotFound => html! { }, } }