Fix effect stack issue
This commit is contained in:
6 files changed
+38
-31
No files matched your search
+23
-18
@@ -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..." },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in new issue
Block a user