diff --git a/packages/hooks/src/lib.rs b/packages/hooks/src/lib.rs index 88a6bdfef6..ec2889e554 100644 --- a/packages/hooks/src/lib.rs +++ b/packages/hooks/src/lib.rs @@ -1,7 +1,7 @@ #![cfg_attr(feature = "nightly-features", feature(debug_refcell))] #[macro_export] -/// A helper macro for using hooks and properties in async environements. +/// A helper macro for using hooks and properties in async environments. /// /// # Usage /// @@ -54,8 +54,8 @@ macro_rules! to_owned { pub mod computed; -mod use_on_unmount; -pub use use_on_unmount::*; +mod use_on_destroy; +pub use use_on_destroy::*; mod use_context; pub use use_context::*; @@ -84,5 +84,7 @@ pub use use_callback::*; mod use_memo; pub use use_memo::*; +mod use_on_create; +pub use use_on_create::*; mod use_root_context; pub use use_root_context::*; diff --git a/packages/hooks/src/use_effect.rs b/packages/hooks/src/use_effect.rs index 76a3f52453..e72afe27f5 100644 --- a/packages/hooks/src/use_effect.rs +++ b/packages/hooks/src/use_effect.rs @@ -3,13 +3,18 @@ use std::{any::Any, cell::Cell, future::Future}; use crate::UseFutureDep; -/// A hook that provides a future that executes after the hooks have been applied +/// A hook that provides a future that executes after the hooks have been applied. /// /// Whenever the hooks dependencies change, the future will be re-evaluated. /// If a future is pending when the dependencies change, the previous future -/// will be allowed to continue +/// will be allowed to continue. /// -/// - dependencies: a tuple of references to values that are `PartialEq` + `Clone` +/// **Note:** If your dependency list is always empty, use [`use_on_create`](crate::use_on_create). +/// +/// ## Arguments +/// +/// - `dependencies`: a tuple of references to values that are `PartialEq` + `Clone`. +/// - `future`: a closure that takes the `dependencies` as arguments and returns a `'static` future. /// /// ## Examples /// diff --git a/packages/hooks/src/use_on_create.rs b/packages/hooks/src/use_on_create.rs new file mode 100644 index 0000000000..28f7bcd6f2 --- /dev/null +++ b/packages/hooks/src/use_on_create.rs @@ -0,0 +1,27 @@ +use dioxus_core::ScopeState; +use std::cell::Cell; +use std::future::Future; + +/// A hook that runs a future when the component is mounted. +/// +/// This is just [`use_effect`](crate::use_effect), but with no dependencies. +/// If you have no dependencies, it's recommended to use this, not just because it's more readable, +/// but also because it's a tiny bit more efficient. +pub fn use_on_create(cx: &ScopeState, future: impl FnOnce() -> F) +where + T: 'static, + F: Future + 'static, +{ + let needs_regen = cx.use_hook(|| Cell::new(true)); + + if needs_regen.get() { + // We don't need regen anymore + needs_regen.set(false); + + let fut = future(); + + cx.push_future(async move { + fut.await; + }); + } +} diff --git a/packages/hooks/src/use_on_unmount.rs b/packages/hooks/src/use_on_destroy.rs similarity index 76% rename from packages/hooks/src/use_on_unmount.rs rename to packages/hooks/src/use_on_destroy.rs index 1309ca1222..8b09b6a20c 100644 --- a/packages/hooks/src/use_on_unmount.rs +++ b/packages/hooks/src/use_on_destroy.rs @@ -1,9 +1,20 @@ -/// Creates 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) +#[deprecated( + note = "Use `use_on_destroy` instead, which has the same functionality. \ +This is deprecated because of the introduction of `use_on_create` which is better mirrored by `use_on_destroy`. \ +The reason why `use_on_create` is not `use_on_mount` is because of potential confusion with `dioxus::events::onmounted`." +)] +pub fn use_on_unmount(cx: &dioxus_core::ScopeState, destroy: D) { + use_on_destroy(cx, destroy); +} + +/// Creates 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`](crate::use_effect)). /// /// Example: /// ```rust /// use dioxus::prelude::*; - +/// /// fn app(cx: Scope) -> Element { /// let state = use_state(cx, || true); /// render! { @@ -25,7 +36,7 @@ /// } /// } /// } - +/// /// fn child_component(cx: Scope) -> Element { /// let original_scroll_position = use_state(cx, || 0.0); /// use_effect(cx, (), move |_| { @@ -38,8 +49,8 @@ /// original_scroll_position.set(window.scroll_y().unwrap()); /// } /// }); - -/// use_on_unmount(cx, { +/// +/// use_on_destroy(cx, { /// to_owned![original_scroll_position]; /// /// restore scroll to the top of the page /// move || { @@ -47,7 +58,7 @@ /// window.scroll_with_x_and_y(*original_scroll_position.current(), 0.0); /// } /// }); - +/// /// render!{ /// div { /// id: "my_element", @@ -56,7 +67,7 @@ /// } /// } /// ``` -pub fn use_on_unmount(cx: &dioxus_core::ScopeState, destroy: D) { +pub fn use_on_destroy(cx: &dioxus_core::ScopeState, destroy: D) { cx.use_hook(|| LifeCycle { ondestroy: Some(destroy), });