Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow functions returning unit in use_effect #2849

Merged
merged 3 commits into from Aug 28, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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)
}