mirror of
https://github.com/DioxusLabs/dioxus
synced 2025-02-17 06:08:26 +00:00
Remove push_future, get use_future kinda working again
This commit is contained in:
parent
14651a3573
commit
a32ae8b112
8 changed files with 49 additions and 60 deletions
|
@ -4,9 +4,6 @@
|
||||||
//! This example shows how to encapsulate state in dioxus components with the reducer pattern.
|
//! This example shows how to encapsulate state in dioxus components with the reducer pattern.
|
||||||
//! This pattern is very useful when a single component can handle many types of input that can
|
//! This pattern is very useful when a single component can handle many types of input that can
|
||||||
//! be represented by an enum.
|
//! be represented by an enum.
|
||||||
//!
|
|
||||||
//! Currently we don't have a reducer pattern hook. If you'd like to add it,
|
|
||||||
//! feel free to make a PR.
|
|
||||||
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
|
@ -15,7 +12,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Element {
|
fn app() -> Element {
|
||||||
let state = use_signal(PlayerState::new);
|
let state = use_signal(|| PlayerState { is_playing: false });
|
||||||
|
|
||||||
rsx!(
|
rsx!(
|
||||||
div {
|
div {
|
||||||
|
@ -38,9 +35,6 @@ struct PlayerState {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PlayerState {
|
impl PlayerState {
|
||||||
fn new() -> Self {
|
|
||||||
Self { is_playing: false }
|
|
||||||
}
|
|
||||||
fn reduce(&mut self, action: PlayerAction) {
|
fn reduce(&mut self, action: PlayerAction) {
|
||||||
match action {
|
match action {
|
||||||
PlayerAction::Pause => self.is_playing = false,
|
PlayerAction::Pause => self.is_playing = false,
|
||||||
|
|
|
@ -62,14 +62,9 @@ pub fn suspend() -> Option<Element> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes the future onto the poll queue to be polled after the component renders.
|
|
||||||
pub fn push_future(fut: impl Future<Output = ()> + 'static) -> Option<Task> {
|
|
||||||
with_current_scope(|cx| cx.push_future(fut))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Spawns the future but does not return the [`TaskId`]
|
/// Spawns the future but does not return the [`TaskId`]
|
||||||
pub fn spawn(fut: impl Future<Output = ()> + 'static) {
|
pub fn spawn(fut: impl Future<Output = ()> + 'static) -> Task {
|
||||||
with_current_scope(|cx| cx.spawn(fut));
|
with_current_scope(|cx| cx.spawn(fut)).expect("to be in a dioxus runtime")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Spawn a future that Dioxus won't clean up when this component is unmounted
|
/// Spawn a future that Dioxus won't clean up when this component is unmounted
|
||||||
|
|
|
@ -87,9 +87,9 @@ pub mod prelude {
|
||||||
pub use crate::innerlude::{
|
pub use crate::innerlude::{
|
||||||
consume_context, consume_context_from_scope, current_scope_id, fc_to_builder, generation,
|
consume_context, consume_context_from_scope, current_scope_id, fc_to_builder, generation,
|
||||||
has_context, needs_update, parent_scope, provide_context, provide_root_context,
|
has_context, needs_update, parent_scope, provide_context, provide_root_context,
|
||||||
push_future, remove_future, schedule_update, schedule_update_any, spawn, spawn_forever,
|
remove_future, schedule_update, schedule_update_any, spawn, spawn_forever, suspend,
|
||||||
suspend, try_consume_context, use_error_boundary, use_hook, AnyValue, Attribute, Component,
|
try_consume_context, use_error_boundary, use_hook, AnyValue, Attribute, Component, Element,
|
||||||
Element, ErrorBoundary, Event, EventHandler, Fragment, HasAttributes, IntoAttributeValue,
|
ErrorBoundary, Event, EventHandler, Fragment, HasAttributes, IntoAttributeValue,
|
||||||
IntoDynNode, Properties, Runtime, RuntimeGuard, ScopeId, ScopeState, Task, Template,
|
IntoDynNode, Properties, Runtime, RuntimeGuard, ScopeId, ScopeState, Task, Template,
|
||||||
TemplateAttribute, TemplateNode, Throw, VNode, VNodeInner, VirtualDom,
|
TemplateAttribute, TemplateNode, Throw, VNode, VNodeInner, VirtualDom,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use futures_util::task::ArcWake;
|
use futures_util::task::ArcWake;
|
||||||
|
|
||||||
use super::SchedulerMsg;
|
use super::SchedulerMsg;
|
||||||
use crate::innerlude::{push_future, remove_future, Runtime};
|
use crate::innerlude::{remove_future, spawn, Runtime};
|
||||||
use crate::ScopeId;
|
use crate::ScopeId;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
@ -28,7 +28,7 @@ impl Task {
|
||||||
/// Spawning a future onto the root scope will cause it to be dropped when the root component is dropped - which
|
/// Spawning a future onto the root scope will cause it to be dropped when the root component is dropped - which
|
||||||
/// will only occur when the VirtualDom itself has been dropped.
|
/// will only occur when the VirtualDom itself has been dropped.
|
||||||
pub fn new(task: impl Future<Output = ()> + 'static) -> Self {
|
pub fn new(task: impl Future<Output = ()> + 'static) -> Self {
|
||||||
push_future(task).expect("to be in a dioxus runtime")
|
spawn(task)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Drop the task immediately.
|
/// Drop the task immediately.
|
||||||
|
|
|
@ -225,18 +225,13 @@ impl ScopeContext {
|
||||||
.expect("Runtime to exist")
|
.expect("Runtime to exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes the future onto the poll queue to be polled after the component renders.
|
/// Spawns the future but does not return the [`TaskId`]
|
||||||
pub fn push_future(&self, fut: impl Future<Output = ()> + 'static) -> Task {
|
pub fn spawn(&self, fut: impl Future<Output = ()> + 'static) -> Task {
|
||||||
let id = with_runtime(|rt| rt.spawn(self.id, fut)).expect("Runtime to exist");
|
let id = with_runtime(|rt| rt.spawn(self.id, fut)).expect("Runtime to exist");
|
||||||
self.spawned_tasks.borrow_mut().insert(id);
|
self.spawned_tasks.borrow_mut().insert(id);
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Spawns the future but does not return the [`TaskId`]
|
|
||||||
pub fn spawn(&self, fut: impl Future<Output = ()> + 'static) {
|
|
||||||
self.push_future(fut);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Spawn a future that Dioxus won't clean up when this component is unmounted
|
/// Spawn a future that Dioxus won't clean up when this component is unmounted
|
||||||
///
|
///
|
||||||
/// This is good for tasks that need to be run after the component has been dropped.
|
/// This is good for tasks that need to be run after the component has been dropped.
|
||||||
|
@ -369,7 +364,7 @@ impl ScopeId {
|
||||||
|
|
||||||
/// Pushes the future onto the poll queue to be polled after the component renders.
|
/// Pushes the future onto the poll queue to be polled after the component renders.
|
||||||
pub fn push_future(self, fut: impl Future<Output = ()> + 'static) -> Option<Task> {
|
pub fn push_future(self, fut: impl Future<Output = ()> + 'static) -> Option<Task> {
|
||||||
with_scope(self, |cx| cx.push_future(fut))
|
with_scope(self, |cx| cx.spawn(fut))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Spawns the future but does not return the [`TaskId`]
|
/// Spawns the future but does not return the [`TaskId`]
|
||||||
|
|
|
@ -21,6 +21,7 @@ tracing = { workspace = true }
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
slab = { workspace = true }
|
slab = { workspace = true }
|
||||||
dioxus-debug-cell = "0.1.1"
|
dioxus-debug-cell = "0.1.1"
|
||||||
|
futures-util = { workspace = true}
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
futures-util = { workspace = true, default-features = false }
|
futures-util = { workspace = true, default-features = false }
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
#![allow(missing_docs)]
|
#![allow(missing_docs)]
|
||||||
use dioxus_core::{ScopeState, Task};
|
use dioxus_core::{
|
||||||
|
prelude::{spawn, use_hook},
|
||||||
|
ScopeState, Task,
|
||||||
|
};
|
||||||
use dioxus_signals::{use_effect, use_signal, Signal};
|
use dioxus_signals::{use_effect, use_signal, Signal};
|
||||||
use std::{any::Any, cell::Cell, future::Future, rc::Rc, sync::Arc};
|
use futures_util::{future, pin_mut, FutureExt};
|
||||||
|
use std::{any::Any, cell::Cell, future::Future, pin::Pin, rc::Rc, sync::Arc, task::Poll};
|
||||||
|
|
||||||
/// A future that resolves to a value.
|
/// A future that resolves to a value.
|
||||||
///
|
///
|
||||||
|
@ -21,22 +25,43 @@ where
|
||||||
T: 'static,
|
T: 'static,
|
||||||
F: Future<Output = T> + 'static,
|
F: Future<Output = T> + 'static,
|
||||||
{
|
{
|
||||||
let task = use_signal(|| None);
|
let value = use_signal(|| None);
|
||||||
|
let state = use_signal(|| UseFutureState::Pending);
|
||||||
|
|
||||||
use_effect(|| {
|
let task = use_signal(|| {
|
||||||
// task.set();
|
// Create the user's task
|
||||||
|
let fut = future();
|
||||||
|
|
||||||
|
// Spawn a wrapper task that polls the innner future and watch its dependencies
|
||||||
|
let task = spawn(async move {
|
||||||
|
// move the future here and pin it so we can ppoll it
|
||||||
|
let mut fut = fut;
|
||||||
|
pin_mut!(fut);
|
||||||
|
|
||||||
|
let res = future::poll_fn(|cx| {
|
||||||
|
// Set the effect stack properly
|
||||||
|
|
||||||
|
// Poll the inner future
|
||||||
|
let ready = fut.poll_unpin(cx);
|
||||||
|
|
||||||
|
// add any dependencies to the effect stack
|
||||||
|
|
||||||
|
ready
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// Set the value
|
||||||
|
value.set(Some(res));
|
||||||
|
});
|
||||||
|
|
||||||
|
Some(task)
|
||||||
});
|
});
|
||||||
//
|
|
||||||
|
|
||||||
UseFuture {
|
UseFuture { task, value, state }
|
||||||
value: todo!(),
|
|
||||||
task,
|
|
||||||
state: todo!(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UseFuture<T: 'static> {
|
pub struct UseFuture<T: 'static> {
|
||||||
value: Signal<T>,
|
value: Signal<Option<T>>,
|
||||||
task: Signal<Option<Task>>,
|
task: Signal<Option<Task>>,
|
||||||
state: Signal<UseFutureState<T>>,
|
state: Signal<UseFutureState<T>>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,27 +42,6 @@ pub fn use_effect(callback: impl FnMut() + 'static) {
|
||||||
use_hook(|| Effect::new(callback));
|
use_hook(|| Effect::new(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new effect. The effect will be run immediately and whenever any signal it reads changes.
|
|
||||||
/// The signal will be owned by the current component and will be dropped when the component is dropped.
|
|
||||||
pub fn use_effect_with_dependencies<D: Dependency>(
|
|
||||||
dependencies: D,
|
|
||||||
mut callback: impl FnMut(D::Out) + 'static,
|
|
||||||
) where
|
|
||||||
D::Out: 'static,
|
|
||||||
{
|
|
||||||
let dependencies_signal = use_signal(|| dependencies.out());
|
|
||||||
use_hook(|| {
|
|
||||||
Effect::new(move || {
|
|
||||||
let deref = &*dependencies_signal.read();
|
|
||||||
callback(deref.clone());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
let changed = { dependencies.changed(&*dependencies_signal.read()) };
|
|
||||||
if changed {
|
|
||||||
dependencies_signal.set(dependencies.out());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Effects allow you to run code when a signal changes. Effects are run immediately and whenever any signal it reads changes.
|
/// Effects allow you to run code when a signal changes. Effects are run immediately and whenever any signal it reads changes.
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub struct Effect {
|
pub struct Effect {
|
||||||
|
|
Loading…
Add table
Reference in a new issue