From 60b25e9c2f32fb8524dfbf08c736aaba836aaf06 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 30 Jun 2023 08:54:08 -0700 Subject: [PATCH 1/2] add on unmount hook --- packages/hooks/src/lib.rs | 3 ++ packages/hooks/src/use_on_unmount.rs | 78 ++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 packages/hooks/src/use_on_unmount.rs diff --git a/packages/hooks/src/lib.rs b/packages/hooks/src/lib.rs index 1e718eda3..ff94fec1e 100644 --- a/packages/hooks/src/lib.rs +++ b/packages/hooks/src/lib.rs @@ -21,6 +21,9 @@ macro_rules! to_owned { )*} } +mod use_on_unmount; +pub use use_on_unmount; + mod usecontext; pub use usecontext::*; diff --git a/packages/hooks/src/use_on_unmount.rs b/packages/hooks/src/use_on_unmount.rs new file mode 100644 index 000000000..528491746 --- /dev/null +++ b/packages/hooks/src/use_on_unmount.rs @@ -0,0 +1,78 @@ +/// Creats a callback that will be run before the component is removed. This can be used to clean up side effects from the component (created with use_effect) +/// +/// Example: +/// ```rust +/// use dioxus::prelude::*; + +/// fn main() { +/// dioxus_web::launch(app) +/// } + +/// fn app(cx: Scope) -> Element { +/// let state = use_state(cx, || true); +/// render! { +/// for _ in 0..100 { +/// h1 { +/// "spacer" +/// } +/// } +/// if **state { +/// render! { +/// child_component {} +/// } +/// } +/// button { +/// onclick: move |_| { +/// state.set(!*state.get()); +/// }, +/// "Unmount element" +/// } +/// } +/// } + +/// fn child_component(cx: Scope) -> Element { +/// let original_scroll_position = use_state(cx, || 0.0); +/// use_effect(cx, (), move |_| { +/// to_owned![original_scroll_position]; +/// async move { +/// let window = web_sys::window().unwrap(); +/// let document = window.document().unwrap(); +/// let element = document.get_element_by_id("my_element").unwrap(); +/// element.scroll_into_view(); +/// original_scroll_position.set(window.scroll_y().unwrap()); +/// } +/// }); + +/// use_on_unmount(cx, { +/// to_owned![original_scroll_position]; +/// /// restore scroll to the top of the page +/// move || { +/// let window = web_sys::window().unwrap(); +/// window.scroll_with_x_and_y(*original_scroll_position.current(), 0.0); +/// } +/// }); + +/// render!{ +/// div { +/// id: "my_element", +/// "hello" +/// } +/// } +/// } +/// ``` +pub fn use_on_unmount(cx: &ScopeState, destroy: D) { + cx.use_hook(|| LifeCycle { + ondestroy: Some(destroy), + }); +} + +struct LifeCycle { + ondestroy: Option, +} + +impl Drop for LifeCycle { + fn drop(&mut self) { + let f = self.ondestroy.take().unwrap(); + f(); + } +} From a6e87cf3400a79f3f1d41a6a3ee45d599a3adc77 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 30 Jun 2023 12:56:22 -0700 Subject: [PATCH 2/2] fix tests --- packages/hooks/Cargo.toml | 1 + packages/hooks/src/lib.rs | 2 +- packages/hooks/src/use_on_unmount.rs | 6 +----- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/hooks/Cargo.toml b/packages/hooks/Cargo.toml index 19d5e53bd..87adebbe4 100644 --- a/packages/hooks/Cargo.toml +++ b/packages/hooks/Cargo.toml @@ -21,3 +21,4 @@ log = { workspace = true } futures-util = { workspace = true, default-features = false } dioxus-core = { workspace = true } dioxus = { workspace = true } +web-sys = { version = "0.3.64", features = ["Document", "Window", "Element"] } diff --git a/packages/hooks/src/lib.rs b/packages/hooks/src/lib.rs index ff94fec1e..de9409650 100644 --- a/packages/hooks/src/lib.rs +++ b/packages/hooks/src/lib.rs @@ -22,7 +22,7 @@ macro_rules! to_owned { } mod use_on_unmount; -pub use use_on_unmount; +pub use use_on_unmount::*; mod usecontext; pub use usecontext::*; diff --git a/packages/hooks/src/use_on_unmount.rs b/packages/hooks/src/use_on_unmount.rs index 528491746..1fa4449c1 100644 --- a/packages/hooks/src/use_on_unmount.rs +++ b/packages/hooks/src/use_on_unmount.rs @@ -4,10 +4,6 @@ /// ```rust /// use dioxus::prelude::*; -/// fn main() { -/// dioxus_web::launch(app) -/// } - /// fn app(cx: Scope) -> Element { /// let state = use_state(cx, || true); /// render! { @@ -60,7 +56,7 @@ /// } /// } /// ``` -pub fn use_on_unmount(cx: &ScopeState, destroy: D) { +pub fn use_on_unmount(cx: &dioxus_core::ScopeState, destroy: D) { cx.use_hook(|| LifeCycle { ondestroy: Some(destroy), });