Bläddra i källkod

Fix effect stack issue

Jonathan Kelley 1 år sedan
förälder
incheckning
bb750f5336

+ 23 - 18
examples/dog_app.rs

@@ -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;
 
 
-    match breed_list.value().read().as_ref() {
-        Some(Ok(breeds)) => rsx! {
-            div { height: "500px",
-                h1 { "Select a dog breed!" }
-                div { display: "flex",
-                    ul { flex: "50%",
-                        for cur_breed in breeds.message.keys().take(10).cloned() {
-                            li { key: "{cur_breed}",
-                                button { onclick: move |_| breed.set(cur_breed.clone()), "{cur_breed}" }
-                            }
-                        }
+        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}"
                     }
                     }
-                    div { flex: "50%", BreedPic { breed } }
                 }
                 }
             }
             }
+        }
+    });
+
+    match breed_list.value().read().as_ref() {
+        Some(resp) => rsx! {
+            h1 { "Select a dog breed!" }
+            div { height: "500px", display: "flex",
+                ul { flex: "50%", {breed_list} }
+                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
packages/core/src/global_context.rs

@@ -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
packages/hooks/src/use_coroutine.rs

@@ -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
packages/hooks/src/use_future.rs

@@ -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
-            let mut fut = fut;
+            // move the future here and pin it so we can poll it
+            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.state.current_val.as_ref().as_ref()
+        self.value
     }
     }
 
 
     /// Get the ID of the future in Dioxus' internal scheduler
     /// Get the ID of the future in Dioxus' internal scheduler

+ 1 - 1
packages/signals/src/effect.rs

@@ -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
packages/signals/src/rt.rs

@@ -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();