Fix effect stack issue

This commit is contained in:
Jonathan Kelley committed 2024-01-15 20:45:59 -08:00
1 parent a32ae8b112
commit bb750f5336
6 files changed
+38 -31

No files matched your search

+23 -18
View File
@@ -7,32 +7,37 @@ fn main() {
fn app() -> Element { fn app() -> Element {
let breed = use_signal(|| "deerhound".to_string()); let breed = use_signal(|| "deerhound".to_string());
let breed_list = use_future(|| async move { let breed_list = use_future(|| async move {
reqwest::get("https://dog.ceo/api/breeds/list/all") let list = reqwest::get("https://dog.ceo/api/breeds/list/all")
.await .await
.unwrap() .unwrap()
.json::<ListBreeds>() .json::<ListBreeds>()
.await .await;
let Ok(breeds) = list else {
return rsx! { "error fetching breeds" };
};
rsx! {
for cur_breed in breeds.message.keys().take(10).cloned() {
li { key: "{cur_breed}",
button { onclick: move |_| breed.set(cur_breed.clone()),
"{cur_breed}"
}
}
}
}
}); });
match breed_list.value().read().as_ref() { match breed_list.value().read().as_ref() {
Some(Ok(breeds)) => rsx! { Some(resp) => rsx! {
div { height: "500px", h1 { "Select a dog breed!" }
h1 { "Select a dog breed!" } div { height: "500px", display: "flex",
div { display: "flex", ul { flex: "50%", {breed_list} }
ul { flex: "50%", div { flex: "50%", BreedPic { breed } }
for cur_breed in breeds.message.keys().take(10).cloned() {
li { key: "{cur_breed}",
button { onclick: move |_| breed.set(cur_breed.clone()), "{cur_breed}" }
}
}
}
div { flex: "50%", BreedPic { breed } }
}
} }
}, },
_ => rsx! { div { "loading breeds" } }, _ => rsx! { "loading breeds..." },
} }
} }
@@ -53,7 +58,7 @@ fn BreedPic(breed: Signal<String>) -> Element {
img { max_width: "500px", max_height: "500px", src: "{resp.message}" } img { max_width: "500px", max_height: "500px", src: "{resp.message}" }
} }
}, },
_ => rsx! { div { "loading dog picture" } }, _ => rsx! { "loading image..." },
} }
} }
+4 -1
View File
@@ -27,7 +27,10 @@ pub fn try_consume_context<T: 'static + Clone>() -> Option<T> {
pub fn consume_context<T: 'static + Clone>() -> T { pub fn consume_context<T: 'static + Clone>() -> T {
with_current_scope(|cx| cx.consume_context::<T>()) with_current_scope(|cx| cx.consume_context::<T>())
.flatten() .flatten()
.unwrap_or_else(|| panic!("Could not find context {}", std::any::type_name::<T>(),)) .expect(&format!(
"Could not find context {}",
std::any::type_name::<T>(),
))
} }
/// Consume context from the current scope /// Consume context from the current scope
+2 -2
View File
@@ -1,4 +1,4 @@
use dioxus_core::prelude::{consume_context, provide_context, push_future, use_hook}; use dioxus_core::prelude::{consume_context, provide_context, spawn, use_hook};
use dioxus_core::Task; use dioxus_core::Task;
use dioxus_signals::{CopyValue, Signal}; use dioxus_signals::{CopyValue, Signal};
pub use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender}; pub use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
@@ -83,7 +83,7 @@ where
// this might not be the best API // this might not be the best API
if *coroutine.needs_regen.read() { if *coroutine.needs_regen.read() {
let (tx, rx) = futures_channel::mpsc::unbounded(); let (tx, rx) = futures_channel::mpsc::unbounded();
let task = push_future(init(rx)).unwrap(); let task = spawn(init(rx));
coroutine.tx.set(Some(tx)); coroutine.tx.set(Some(tx));
coroutine.task.set(Some(task)); coroutine.task.set(Some(task));
coroutine.needs_regen.set_untracked(false); coroutine.needs_regen.set_untracked(false);
+7 -8
View File
@@ -3,7 +3,7 @@ use dioxus_core::{
prelude::{spawn, use_hook}, prelude::{spawn, use_hook},
ScopeState, Task, ScopeState, Task,
}; };
use dioxus_signals::{use_effect, use_signal, Signal}; use dioxus_signals::{use_effect, use_signal, Effect, Signal};
use futures_util::{future, pin_mut, FutureExt}; use futures_util::{future, pin_mut, FutureExt};
use std::{any::Any, cell::Cell, future::Future, pin::Pin, rc::Rc, sync::Arc, task::Poll}; use std::{any::Any, cell::Cell, future::Future, pin::Pin, rc::Rc, sync::Arc, task::Poll};
@@ -20,7 +20,7 @@ use std::{any::Any, cell::Cell, future::Future, pin::Pin, rc::Rc, sync::Arc, tas
/// will be canceled before the new one is started. /// will be canceled before the new one is started.
/// ///
/// - dependencies: a tuple of references to values that are PartialEq + Clone /// - dependencies: a tuple of references to values that are PartialEq + Clone
pub fn use_future<T, F>(future: impl FnMut() -> F) -> UseFuture<T> pub fn use_future<T, F>(mut future: impl FnMut() -> F) -> UseFuture<T>
where where
T: 'static, T: 'static,
F: Future<Output = T> + 'static, F: Future<Output = T> + 'static,
@@ -34,8 +34,8 @@ where
// Spawn a wrapper task that polls the innner future and watch its dependencies // Spawn a wrapper task that polls the innner future and watch its dependencies
let task = spawn(async move { let task = spawn(async move {
// move the future here and pin it so we can ppoll it // move the future here and pin it so we can poll it
let mut fut = fut; let fut = fut;
pin_mut!(fut); pin_mut!(fut);
let res = future::poll_fn(|cx| { let res = future::poll_fn(|cx| {
@@ -44,7 +44,7 @@ where
// Poll the inner future // Poll the inner future
let ready = fut.poll_unpin(cx); let ready = fut.poll_unpin(cx);
// add any dependencies to the effect stack // add any dependencies to the effect stack that we need to watch when restarting the future
ready ready
}) })
@@ -85,15 +85,14 @@ impl<T> UseFuture<T> {
// Manually set the value in the future slot without starting the future over // Manually set the value in the future slot without starting the future over
pub fn set(&self, new_value: T) { pub fn set(&self, new_value: T) {
// self.state.set(Some(new_value)); self.value.set(Some(new_value));
} }
/// Return any value, even old values if the future has not yet resolved. /// Return any value, even old values if the future has not yet resolved.
/// ///
/// If the future has never completed, the returned value will be `None`. /// If the future has never completed, the returned value will be `None`.
pub fn value(&self) -> Signal<Option<T>> { pub fn value(&self) -> Signal<Option<T>> {
todo!() self.value
// self.state.current_val.as_ref().as_ref()
} }
/// Get the ID of the future in Dioxus' internal scheduler /// Get the ID of the future in Dioxus' internal scheduler
+1 -1
View File
@@ -26,7 +26,7 @@ impl EffectStack {
} }
pub(crate) fn get_effect_stack() -> EffectStack { pub(crate) fn get_effect_stack() -> EffectStack {
match consume_context() { match try_consume_context() {
Some(rt) => rt, Some(rt) => rt,
None => { None => {
let store = EffectStack::default(); let store = EffectStack::default();
+1 -1
View File
@@ -12,7 +12,7 @@ use generational_box::{
use crate::Effect; use crate::Effect;
fn current_store() -> Store { fn current_store() -> Store {
match consume_context() { match try_consume_context::<Store>() {
Some(rt) => rt, Some(rt) => rt,
None => { None => {
let store = Store::default(); let store = Store::default();