create a global once function

This commit is contained in:
Evan Almloff 2024-01-05 12:31:20 -06:00
parent a1676537ad
commit a4a9aa5224
2 changed files with 35 additions and 9 deletions

View file

@ -73,9 +73,9 @@ pub(crate) mod 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,
};
@ -84,11 +84,11 @@ pub use crate::innerlude::{
/// This includes types like [`Scope`], [`Element`], and [`Component`].
pub mod prelude {
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,
};
}

View file

@ -269,7 +269,6 @@ impl ScopeContext {
/// cx.use_hook(|| println!("Hello, world!"));
/// }
/// ```
#[allow(clippy::mut_from_ref)]
pub fn use_hook<State: Clone + 'static>(&self, initializer: impl FnOnce() -> State) -> State {
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.");
@ -398,3 +397,30 @@ pub fn spawn_forever(fut: impl Future<Output = ()> + 'static) -> Option<TaskId>
pub fn remove_future(id: TaskId) {
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")
}