wip: upgrade hooks
This commit is contained in:
1 parent
c0e0196a67
commit
b3ac2ee3f7
10 files changed
+150
-44
No files matched your search
@@ -13,5 +13,8 @@ pub use usecoroutine::*;
|
||||
mod usefuture;
|
||||
pub use usefuture::*;
|
||||
|
||||
mod usesuspense;
|
||||
pub use usesuspense::*;
|
||||
|
||||
// mod usemodel;
|
||||
// pub use usemodel::*;
|
||||
@@ -1,4 +1,4 @@
|
||||
use dioxus_core::ScopeState;
|
||||
use dioxus_core::{ScopeState, TaskId};
|
||||
use std::future::Future;
|
||||
use std::{cell::Cell, pin::Pin, rc::Rc};
|
||||
/*
|
||||
@@ -23,15 +23,17 @@ where
|
||||
F: Future<Output = ()> + 'static,
|
||||
{
|
||||
cx.use_hook(
|
||||
move |_| State {
|
||||
running: Default::default(),
|
||||
pending_fut: Default::default(),
|
||||
running_fut: Default::default(),
|
||||
},
|
||||
|state| {
|
||||
move |_| {
|
||||
let f = create_future();
|
||||
let id = cx.push_future(f);
|
||||
|
||||
State {
|
||||
running: Default::default(),
|
||||
id
|
||||
// pending_fut: Default::default(),
|
||||
// running_fut: Default::default(),
|
||||
}
|
||||
},
|
||||
|state| {
|
||||
// state.pending_fut.set(Some(Box::pin(f)));
|
||||
|
||||
// if let Some(fut) = state.running_fut.as_mut() {
|
||||
@@ -74,13 +76,13 @@ where
|
||||
|
||||
struct State {
|
||||
running: Rc<Cell<bool>>,
|
||||
|
||||
id: TaskId,
|
||||
// the way this is structure, you can toggle the coroutine without re-rendering the comppnent
|
||||
// this means every render *generates* the future, which is a bit of a waste
|
||||
// todo: allocate pending futures in the bump allocator and then have a true promotion
|
||||
pending_fut: Cell<Option<Pin<Box<dyn Future<Output = ()> + 'static>>>>,
|
||||
running_fut: Option<Pin<Box<dyn Future<Output = ()> + 'static>>>,
|
||||
// running_fut: Rc<RefCell<Option<Pin<Box<dyn Future<Output = ()> + 'static>>>>>,
|
||||
// pending_fut: Cell<Option<Pin<Box<dyn Future<Output = ()> + 'static>>>>,
|
||||
// running_fut: Option<Pin<Box<dyn Future<Output = ()> + 'static>>>,
|
||||
// running_fut: Rc<RefCell<Option<Pin<Box<dyn Future<Output = ()> + 'static>>>>>
|
||||
}
|
||||
|
||||
pub struct CoroutineHandle<'a> {
|
||||
@@ -104,11 +106,11 @@ impl<'a> CoroutineHandle<'a> {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(submit) = self.inner.pending_fut.take() {
|
||||
// submit();
|
||||
// let inner = self.inner;
|
||||
// self.cx.push_task(submit());
|
||||
}
|
||||
// if let Some(submit) = self.inner.pending_fut.take() {
|
||||
// submit();
|
||||
// let inner = self.inner;
|
||||
// self.cx.push_task(submit());
|
||||
// }
|
||||
}
|
||||
|
||||
pub fn is_running(&self) -> bool {
|
||||
|
||||
@@ -1,30 +1,52 @@
|
||||
use dioxus_core::{ScopeState, TaskId};
|
||||
use std::{cell::Cell, future::Future};
|
||||
use std::{cell::Cell, future::Future, rc::Rc};
|
||||
|
||||
pub fn use_future<'a, T: 'static, F: Future<Output = T>>(
|
||||
pub fn use_future<'a, T: 'static, F: Future<Output = T> + 'static>(
|
||||
cx: &'a ScopeState,
|
||||
f: impl FnOnce() -> F,
|
||||
) -> FutureHandle<'a, T> {
|
||||
) -> (Option<&T>, FutureHandle<'a, T>) {
|
||||
cx.use_hook(
|
||||
|_| {
|
||||
//
|
||||
let fut = f();
|
||||
let slot = Rc::new(Cell::new(None));
|
||||
let updater = cx.schedule_update();
|
||||
|
||||
let _slot = slot.clone();
|
||||
let new_fut = async move {
|
||||
let res = fut.await;
|
||||
_slot.set(Some(res));
|
||||
updater();
|
||||
};
|
||||
let task = cx.push_future(new_fut);
|
||||
|
||||
UseFutureInner {
|
||||
needs_regen: true,
|
||||
task: None,
|
||||
slot,
|
||||
value: None,
|
||||
task: Some(task),
|
||||
}
|
||||
},
|
||||
|_| {
|
||||
//
|
||||
FutureHandle {
|
||||
cx,
|
||||
value: Cell::new(None),
|
||||
|state| {
|
||||
if let Some(value) = state.slot.take() {
|
||||
state.value = Some(value);
|
||||
state.task = None;
|
||||
}
|
||||
(
|
||||
state.value.as_ref(),
|
||||
FutureHandle {
|
||||
cx,
|
||||
value: Cell::new(None),
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
struct UseFutureInner {
|
||||
struct UseFutureInner<T> {
|
||||
needs_regen: bool,
|
||||
value: Option<T>,
|
||||
slot: Rc<Cell<Option<T>>>,
|
||||
task: Option<TaskId>,
|
||||
}
|
||||
|
||||
|
||||
@@ -287,11 +287,16 @@ pub struct AsyncUseState<T: 'static> {
|
||||
wip: Rc<RefCell<Option<T>>>,
|
||||
}
|
||||
|
||||
impl<T: ToOwned> AsyncUseState<T> {
|
||||
impl<T: ToOwned<Owned = T>> AsyncUseState<T> {
|
||||
pub fn get_mut<'a>(&'a self) -> RefMut<'a, T> {
|
||||
// make sure we get processed
|
||||
// self.needs_update();
|
||||
|
||||
{
|
||||
let mut wip = self.wip.borrow_mut();
|
||||
if wip.is_none() {
|
||||
*wip = Some(self.inner.as_ref().to_owned());
|
||||
}
|
||||
(self.re_render)();
|
||||
}
|
||||
// Bring out the new value, cloning if it we need to
|
||||
// "get_mut" is locked behind "ToOwned" to make it explicit that cloning occurs to use this
|
||||
RefMut::map(self.wip.borrow_mut(), |slot| {
|
||||
@@ -305,9 +310,10 @@ impl<T> AsyncUseState<T> {
|
||||
(self.re_render)();
|
||||
*self.wip.borrow_mut() = Some(val);
|
||||
}
|
||||
pub fn get(&self) -> &T {
|
||||
self.inner.as_ref()
|
||||
}
|
||||
|
||||
// pub fn get(&self) -> Ref<'_, T> {
|
||||
// self.wip.borrow
|
||||
// }
|
||||
|
||||
pub fn get_rc(&self) -> &Rc<T> {
|
||||
&self.inner
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
use std::{cell::Cell, future::Future, rc::Rc};
|
||||
|
||||
use dioxus_core::{Element, ScopeState, TaskId};
|
||||
|
||||
pub fn use_suspense<R: 'static, F: Future<Output = R> + 'static>(
|
||||
cx: &ScopeState,
|
||||
create_future: impl FnOnce() -> F,
|
||||
render: impl FnOnce(&R) -> Element,
|
||||
) -> Element {
|
||||
cx.use_hook(
|
||||
|_| {
|
||||
let fut = create_future();
|
||||
|
||||
let wip_value: Rc<Cell<Option<R>>> = Default::default();
|
||||
|
||||
let wip = wip_value.clone();
|
||||
let new_fut = async move {
|
||||
let val = fut.await;
|
||||
wip.set(Some(val));
|
||||
};
|
||||
|
||||
let task = cx.push_future(new_fut);
|
||||
SuspenseInner {
|
||||
task,
|
||||
value: None,
|
||||
wip_value,
|
||||
}
|
||||
},
|
||||
|sus| {
|
||||
if let Some(value) = sus.value.as_ref() {
|
||||
render(&value)
|
||||
} else {
|
||||
// generate a placeholder node if the future isnt ready
|
||||
None
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
struct SuspenseInner<R> {
|
||||
task: TaskId,
|
||||
wip_value: Rc<Cell<Option<R>>>,
|
||||
value: Option<R>,
|
||||
}
|
||||
Reference in new issue
Block a user