Add lazy contexts to signals

This commit is contained in:
Jonathan Kelley committed 2023-07-14 12:52:49 -07:00
1 parent 645706c7f4
commit 2d8841cf70
5 files changed
+40 -6

No files matched your search

+1 -4
View File
@@ -1,5 +1,4 @@
use dioxus::prelude::*;
use dioxus_signals::{use_init_signal_rt, use_signal};
use std::time::Duration;
fn main() {
@@ -7,9 +6,7 @@ fn main() {
}
fn app(cx: Scope) -> Element {
use_init_signal_rt(cx);
let mut count = use_signal(cx, || 0);
let mut count = dioxus_signals::use_signal(cx, || 0);
use_future!(cx, || async move {
loop {
+19
View File
@@ -418,6 +418,25 @@ impl<'src> ScopeState {
value
}
/// Provide a context to the root and then consume it
///
/// This is intended for "global" state management solutions that would rather be implicit for the entire app.
/// Things like signal runtimes and routers are examples of "singletons" that would benefit from lazy initialization.
///
/// Note that you should be checking if the context existed before trying to provide a new one. Providing a context
/// when a context already exists will swap the context out for the new one, which may not be what you want.
pub fn provide_root_context<T: 'static + Clone>(&self, context: T) -> T {
let mut parent = self;
// Walk upwards until there is no more parent - and tada we have the root
while let Some(next_parent) = parent.parent {
parent = unsafe { &*next_parent };
debug_assert_eq!(parent.scope_id(), ScopeId(0));
}
parent.provide_context(context)
}
/// Pushes the future onto the poll queue to be polled after the component renders.
pub fn push_future(&self, fut: impl Future<Output = ()> + 'static) -> TaskId {
let id = self.tasks.spawn(self.id, fut);
+3
View File
@@ -79,3 +79,6 @@ pub use usecallback::*;
mod usememo;
pub use usememo::*;
mod userootcontext;
pub use userootcontext::*;
+9
View File
@@ -0,0 +1,9 @@
use dioxus_core::ScopeState;
///
pub fn use_root_context<T: 'static + Clone>(cx: &ScopeState, new: impl FnOnce() -> T) -> &T {
cx.use_hook(|| {
cx.consume_context::<T>()
.unwrap_or_else(|| cx.provide_root_context(new()))
})
}
+8 -2
View File
@@ -10,16 +10,22 @@ mod rt;
use dioxus_core::ScopeState;
pub use rt::*;
use crate::rt::claim_rt;
pub fn use_init_signal_rt(cx: &ScopeState) {
cx.use_hook(|| {
let rt = crate::rt::claim_rt(cx.schedule_update_any());
let rt = claim_rt(cx.schedule_update_any());
cx.provide_context(rt);
});
}
pub fn use_signal<T: 'static>(cx: &ScopeState, f: impl FnOnce() -> T) -> Signal<T> {
cx.use_hook(|| {
let rt: &'static SignalRt = cx.consume_context().unwrap();
let rt: &'static SignalRt = match cx.consume_context() {
Some(rt) => rt,
None => cx.provide_context(claim_rt(cx.schedule_update_any())),
};
let id = rt.init(f());
rt.subscribe(id, cx.scope_id());