Explorar el Código

create a global once function

Evan Almloff hace 1 año
padre
commit
a4a9aa5224
Se han modificado 2 ficheros con 35 adiciones y 9 borrados
  1. 8 8
      packages/core/src/lib.rs
  2. 27 1
      packages/core/src/scope_context.rs

+ 8 - 8
packages/core/src/lib.rs

@@ -73,9 +73,9 @@ pub(crate) mod innerlude {
 }
 }
 
 
 pub use crate::innerlude::{
 pub use crate::innerlude::{
-    fc_to_builder, vdom_is_rendering, AnyValue, Attribute, AttributeValue, CapturedError,
-    Component, DynamicNode, Element, ElementId, Event, Fragment, IntoDynNode, Mutation,
-    MutationsVec, Properties, RenderReturn, ScopeId, ScopeState, TaskId, Template,
+    fc_to_builder, generation, once, vdom_is_rendering, AnyValue, Attribute, AttributeValue,
+    CapturedError, Component, DynamicNode, Element, ElementId, Event, Fragment, IntoDynNode,
+    Mutation, MutationsVec, Properties, RenderReturn, ScopeId, ScopeState, TaskId, Template,
     TemplateAttribute, TemplateNode, VComponent, VNode, VPlaceholder, VText, VirtualDom,
     TemplateAttribute, TemplateNode, VComponent, VNode, VPlaceholder, VText, VirtualDom,
 };
 };
 
 
@@ -84,11 +84,11 @@ pub use crate::innerlude::{
 /// This includes types like [`Scope`], [`Element`], and [`Component`].
 /// This includes types like [`Scope`], [`Element`], and [`Component`].
 pub mod prelude {
 pub mod prelude {
     pub use crate::innerlude::{
     pub use crate::innerlude::{
-        consume_context, consume_context_from_scope, current_scope_id, fc_to_builder, has_context,
-        provide_context, provide_context_to_scope, provide_root_context, push_future,
-        remove_future, schedule_update_any, spawn, spawn_forever, suspend, use_error_boundary,
-        AnyValue, Component, Element, ErrorBoundary, Event, EventHandler, Fragment,
-        IntoAttributeValue, IntoDynNode, Properties, Runtime, RuntimeGuard, ScopeId, ScopeState,
+        consume_context, consume_context_from_scope, current_scope_id, fc_to_builder, generation,
+        has_context, once, provide_context, provide_context_to_scope, provide_root_context,
+        push_future, remove_future, schedule_update_any, spawn, spawn_forever, suspend,
+        use_error_boundary, AnyValue, Component, Element, ErrorBoundary, Event, EventHandler,
+        Fragment, IntoAttributeValue, IntoDynNode, Properties, Runtime, RuntimeGuard, ScopeId,
         TaskId, Template, TemplateAttribute, TemplateNode, Throw, VNode, VirtualDom,
         TaskId, Template, TemplateAttribute, TemplateNode, Throw, VNode, VirtualDom,
     };
     };
 }
 }

+ 27 - 1
packages/core/src/scope_context.rs

@@ -269,7 +269,6 @@ impl ScopeContext {
     ///     cx.use_hook(|| println!("Hello, world!"));
     ///     cx.use_hook(|| println!("Hello, world!"));
     /// }
     /// }
     /// ```
     /// ```
-    #[allow(clippy::mut_from_ref)]
     pub fn use_hook<State: Clone + 'static>(&self, initializer: impl FnOnce() -> State) -> State {
     pub fn use_hook<State: Clone + 'static>(&self, initializer: impl FnOnce() -> State) -> State {
         let cur_hook = self.hook_index.get();
         let cur_hook = self.hook_index.get();
         let mut hooks = self.hooks.try_borrow_mut().expect("The hook list is already borrowed: This error is likely caused by trying to use a hook inside a hook which violates the rules of hooks.");
         let mut hooks = self.hooks.try_borrow_mut().expect("The hook list is already borrowed: This error is likely caused by trying to use a hook inside a hook which violates the rules of hooks.");
@@ -398,3 +397,30 @@ pub fn spawn_forever(fut: impl Future<Output = ()> + 'static) -> Option<TaskId>
 pub fn remove_future(id: TaskId) {
 pub fn remove_future(id: TaskId) {
     with_current_scope(|cx| cx.remove_future(id));
     with_current_scope(|cx| cx.remove_future(id));
 }
 }
+
+/// Store a value between renders. The foundational hook for all other hooks.
+///
+/// Accepts an `initializer` closure, which is run on the first use of the hook (typically the initial render). The return value of this closure is stored for the lifetime of the component, and a mutable reference to it is provided on every render as the return value of `use_hook`.
+///
+/// When the component is unmounted (removed from the UI), the value is dropped. This means you can return a custom type and provide cleanup code by implementing the [`Drop`] trait
+///
+/// # Example
+///
+/// ```
+/// use dioxus_core::ScopeState;
+///
+/// // prints a greeting on the initial render
+/// pub fn use_hello_world() {
+///     once(|| println!("Hello, world!"));
+/// }
+/// ```
+pub fn once<State: Clone + 'static>(initializer: impl FnOnce() -> State) -> State {
+    with_current_scope(|cx| cx.use_hook(initializer)).expect("to be in a dioxus runtime")
+}
+
+/// Get the current render since the inception of this component
+///
+/// This can be used as a helpful diagnostic when debugging hooks/renders, etc
+pub fn generation() -> Option<usize> {
+    with_current_scope(|cx| Some(cx.generation())).expect("to be in a dioxus runtime")
+}