Skip to content

Commit

Permalink
Allow functions returning unit in use_effect (#2849)
Browse files Browse the repository at this point in the history
* Use TearDown trait as destructor for use_effect

* Docs

* no default tear_down
  • Loading branch information
hamza1311 committed Aug 28, 2022
1 parent cffb7c5 commit 0e0d694
Showing 1 changed file with 41 additions and 12 deletions.
53 changes: 41 additions & 12 deletions packages/yew/src/functional/hooks/use_effect.rs
Expand Up @@ -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<F: FnOnce() + 'static> TearDown for F {
fn tear_down(self) {
self()
}
}

struct UseEffectBase<T, F, D>
where
F: FnOnce(&T) -> D + 'static,
T: 'static,
D: FnOnce() + 'static,
D: TearDown,
{
runner_with_deps: Option<(T, F)>,
destructor: Option<D>,
Expand All @@ -18,7 +34,7 @@ impl<T, F, D> Effect for RefCell<UseEffectBase<T, F, D>>
where
F: FnOnce(&T) -> D + 'static,
T: 'static,
D: FnOnce() + 'static,
D: TearDown,
{
fn rendered(&self) {
let mut this = self.borrow_mut();
Expand All @@ -29,7 +45,7 @@ where
}

if let Some(de) = this.destructor.take() {
de();
de.tear_down();
}

let new_destructor = runner(&deps);
Expand All @@ -44,11 +60,11 @@ impl<T, F, D> Drop for UseEffectBase<T, F, D>
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()
}
}
}
Expand All @@ -60,13 +76,13 @@ fn use_effect_base<T, D>(
) -> impl Hook<Output = ()>
where
T: 'static,
D: FnOnce() + 'static,
D: TearDown,
{
struct HookProvider<T, F, D>
where
F: FnOnce(&T) -> D + 'static,
T: 'static,
D: FnOnce() + 'static,
D: TearDown,
{
runner: F,
deps: T,
Expand All @@ -77,7 +93,7 @@ where
where
F: FnOnce(&T) -> D + 'static,
T: 'static,
D: FnOnce() + 'static,
D: TearDown,
{
type Output = ();

Expand Down Expand Up @@ -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, D>(f: F)
where
F: FnOnce() -> D + 'static,
D: FnOnce() + 'static,
D: TearDown,
{
use_effect_base(|_| f(), (), |_, _| true);
}
Expand Down Expand Up @@ -176,7 +201,6 @@ where
/// use_effect_with_deps(
/// move |_| {
/// log!(" Is loading prop changed!");
/// || ()
/// },
/// is_loading,
/// );
Expand All @@ -201,7 +225,6 @@ where
/// use_effect_with_deps(
/// move |_| {
/// log!("I got rendered, yay!");
/// || ()
/// },
/// (),
/// );
Expand Down Expand Up @@ -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<T, F, D>(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)
}

0 comments on commit 0e0d694

Please sign in to comment.