feat: context api overhaul
This commit is contained in:
1 parent
11a45c8ef0
commit
a61daf220d
44 files changed
+812
-621
No files matched your search
@@ -21,14 +21,17 @@ macro_rules! to_owned {
|
||||
)*}
|
||||
}
|
||||
|
||||
mod usecontext;
|
||||
pub use usecontext::*;
|
||||
|
||||
mod usestate;
|
||||
pub use usestate::{use_state, UseState};
|
||||
|
||||
mod useref;
|
||||
pub use useref::*;
|
||||
|
||||
mod use_shared_state;
|
||||
pub use use_shared_state::*;
|
||||
// mod use_shared_state;
|
||||
// pub use use_shared_state::*;
|
||||
|
||||
mod usecoroutine;
|
||||
pub use usecoroutine::*;
|
||||
|
||||
@@ -63,7 +63,7 @@ impl<T> ProvidedStateInner<T> {
|
||||
pub fn use_context<T: 'static>(cx: &ScopeState) -> Option<UseSharedState<T>> {
|
||||
let state = cx.use_hook(|| {
|
||||
let scope_id = cx.scope_id();
|
||||
let root = cx.consume_context::<ProvidedState<T>>();
|
||||
let root = cx.consume_context::<ProvidedState<T>>().cloned();
|
||||
|
||||
if let Some(root) = root.as_ref() {
|
||||
root.borrow_mut().consumers.insert(scope_id);
|
||||
@@ -179,6 +179,7 @@ pub fn use_context_provider<T: 'static>(cx: &ScopeState, f: impl FnOnce() -> T)
|
||||
notify_any: cx.schedule_update_any(),
|
||||
consumers: HashSet::new(),
|
||||
}));
|
||||
cx.provide_context(state)
|
||||
|
||||
cx.provide_context(state);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
use dioxus_core::ScopeState;
|
||||
|
||||
/// Consume some context in the tree
|
||||
pub fn use_context<T: 'static>(cx: &ScopeState) -> Option<&T> {
|
||||
match *cx.use_hook(|| cx.consume_context::<T>().map(|t| t as *const T)) {
|
||||
Some(res) => Some(unsafe { &*res }),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Provide some context via the tree and return a reference to it
|
||||
///
|
||||
/// Once the context has been provided, it is immutable. Mutations should be done via interior mutability.
|
||||
pub fn use_context_provider<T: 'static>(cx: &ScopeState, f: impl FnOnce() -> T) -> &T {
|
||||
let ptr = *cx.use_hook(|| cx.provide_context(f()) as *const T);
|
||||
unsafe { &*ptr }
|
||||
}
|
||||
@@ -2,6 +2,8 @@ use dioxus_core::{ScopeState, TaskId};
|
||||
pub use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
|
||||
use std::future::Future;
|
||||
|
||||
use crate::{use_context, use_context_provider};
|
||||
|
||||
/// Maintain a handle over a future that can be paused, resumed, and canceled.
|
||||
///
|
||||
/// This is an upgraded form of [`use_future`] with an integrated channel system.
|
||||
@@ -59,33 +61,33 @@ use std::future::Future;
|
||||
/// }
|
||||
/// })
|
||||
/// ```
|
||||
pub fn use_coroutine<M, G, F>(cx: &ScopeState, init: G) -> &CoroutineHandle<M>
|
||||
pub fn use_coroutine<M, G, F>(cx: &ScopeState, init: G) -> &Coroutine<M>
|
||||
where
|
||||
M: 'static,
|
||||
G: FnOnce(UnboundedReceiver<M>) -> F,
|
||||
F: Future<Output = ()> + 'static,
|
||||
{
|
||||
cx.use_hook(|| {
|
||||
use_context_provider(cx, || {
|
||||
let (tx, rx) = futures_channel::mpsc::unbounded();
|
||||
let task = cx.push_future(init(rx));
|
||||
cx.provide_context(CoroutineHandle { tx, task })
|
||||
Coroutine { tx, task }
|
||||
})
|
||||
}
|
||||
|
||||
/// Get a handle to a coroutine higher in the tree
|
||||
///
|
||||
/// See the docs for [`use_coroutine`] for more details.
|
||||
pub fn use_coroutine_handle<M: 'static>(cx: &ScopeState) -> Option<&CoroutineHandle<M>> {
|
||||
cx.use_hook(|| cx.consume_context::<CoroutineHandle<M>>())
|
||||
.as_ref()
|
||||
pub fn use_coroutine_handle<M: 'static>(cx: &ScopeState) -> Option<&Coroutine<M>> {
|
||||
use_context::<Coroutine<M>>(cx)
|
||||
}
|
||||
|
||||
pub struct CoroutineHandle<T> {
|
||||
pub struct Coroutine<T> {
|
||||
tx: UnboundedSender<T>,
|
||||
task: TaskId,
|
||||
}
|
||||
|
||||
impl<T> Clone for CoroutineHandle<T> {
|
||||
// for use in futures
|
||||
impl<T> Clone for Coroutine<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
tx: self.tx.clone(),
|
||||
@@ -94,7 +96,7 @@ impl<T> Clone for CoroutineHandle<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CoroutineHandle<T> {
|
||||
impl<T> Coroutine<T> {
|
||||
/// Get the ID of this coroutine
|
||||
#[must_use]
|
||||
pub fn task_id(&self) -> TaskId {
|
||||
@@ -112,8 +114,8 @@ mod tests {
|
||||
#![allow(unused)]
|
||||
|
||||
use super::*;
|
||||
use dioxus_core::exports::futures_channel::mpsc::unbounded;
|
||||
use dioxus_core::prelude::*;
|
||||
use futures_channel::mpsc::unbounded;
|
||||
use futures_util::StreamExt;
|
||||
|
||||
fn app(cx: Scope, name: String) -> Element {
|
||||
@@ -127,7 +129,7 @@ mod tests {
|
||||
|
||||
let task3 = use_coroutine(&cx, |rx| complex_task(rx, 10));
|
||||
|
||||
None
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn view_task(mut rx: UnboundedReceiver<i32>) {
|
||||
|
||||
@@ -86,7 +86,7 @@ mod tests {
|
||||
//
|
||||
});
|
||||
|
||||
None
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -343,7 +343,7 @@ mod tests {
|
||||
|
||||
let g = fut.await;
|
||||
|
||||
None
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -466,7 +466,7 @@ fn api_makes_sense() {
|
||||
}
|
||||
|
||||
cx.spawn({
|
||||
dioxus_core::to_owned![val];
|
||||
to_owned![val];
|
||||
async move {
|
||||
val.modify(|f| f + 1);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user