diff --git a/packages/yew/src/functional/hooks/use_effect.rs b/packages/yew/src/functional/hooks/use_effect.rs index a01cb2cf58f..16752ef5c8d 100644 --- a/packages/yew/src/functional/hooks/use_effect.rs +++ b/packages/yew/src/functional/hooks/use_effect.rs @@ -2,11 +2,27 @@ use std::cell::RefCell; use crate::functional::{hook, Effect, Hook, HookContext}; +/// Trait describing the destructor of [`use_effect`] hook. +pub trait TearDown: Sized + 'static { + /// The function that is executed when destructor is called + fn tear_down(self); +} + +impl TearDown for () { + fn tear_down(self) {} +} + +impl TearDown for F { + fn tear_down(self) { + self() + } +} + struct UseEffectBase where F: FnOnce(&T) -> D + 'static, T: 'static, - D: FnOnce() + 'static, + D: TearDown, { runner_with_deps: Option<(T, F)>, destructor: Option, @@ -18,7 +34,7 @@ impl Effect for RefCell> where F: FnOnce(&T) -> D + 'static, T: 'static, - D: FnOnce() + 'static, + D: TearDown, { fn rendered(&self) { let mut this = self.borrow_mut(); @@ -29,7 +45,7 @@ where } if let Some(de) = this.destructor.take() { - de(); + de.tear_down(); } let new_destructor = runner(&deps); @@ -44,11 +60,11 @@ impl Drop for UseEffectBase where F: FnOnce(&T) -> D + 'static, T: 'static, - D: FnOnce() + 'static, + D: TearDown, { fn drop(&mut self) { if let Some(destructor) = self.destructor.take() { - destructor() + destructor.tear_down() } } } @@ -60,13 +76,13 @@ fn use_effect_base( ) -> impl Hook where T: 'static, - D: FnOnce() + 'static, + D: TearDown, { struct HookProvider where F: FnOnce(&T) -> D + 'static, T: 'static, - D: FnOnce() + 'static, + D: TearDown, { runner: F, deps: T, @@ -77,7 +93,7 @@ where where F: FnOnce(&T) -> D + 'static, T: 'static, - D: FnOnce() + 'static, + D: TearDown, { type Output = (); @@ -141,11 +157,20 @@ where /// } /// } /// ``` +/// +/// # Destructor +/// +/// Any type implementing [`TearDown`] can be used as destructor, which is called when the component +/// is re-rendered +/// +/// ## Tip +/// +/// The callback can return [`()`] if there is no destructor to run. #[hook] pub fn use_effect(f: F) where F: FnOnce() -> D + 'static, - D: FnOnce() + 'static, + D: TearDown, { use_effect_base(|_| f(), (), |_, _| true); } @@ -176,7 +201,6 @@ where /// use_effect_with_deps( /// move |_| { /// log!(" Is loading prop changed!"); -/// || () /// }, /// is_loading, /// ); @@ -201,7 +225,6 @@ where /// use_effect_with_deps( /// move |_| { /// log!("I got rendered, yay!"); -/// || () /// }, /// (), /// ); @@ -232,12 +255,18 @@ where /// html! { "Hello" } /// } /// ``` +/// +/// Any type implementing [`TearDown`] can be used as destructor +/// +/// ### Tip +/// +/// The callback can return [`()`] if there is no destructor to run. #[hook] pub fn use_effect_with_deps(f: F, deps: T) where T: PartialEq + 'static, F: FnOnce(&T) -> D + 'static, - D: FnOnce() + 'static, + D: TearDown, { use_effect_base(f, deps, |lhs, rhs| lhs != rhs) }