From 69e4ebe4ed630d6e9d765e820a17f46196a0fc1b Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Mon, 5 Feb 2024 11:59:50 -0800 Subject: [PATCH] Fix suspense on resource --- examples/dog_app.rs | 15 +++++++-------- examples/suspense.rs | 4 ++-- packages/hooks/src/use_resource.rs | 28 +++++++++++++--------------- 3 files changed, 22 insertions(+), 25 deletions(-) diff --git a/examples/dog_app.rs b/examples/dog_app.rs index a9c21fdfb..4d3005f97 100644 --- a/examples/dog_app.rs +++ b/examples/dog_app.rs @@ -29,7 +29,7 @@ fn app() -> Element { } }); - let Some(breed_list) = breed_list.value().cloned() else { + let Some(breed_list) = breed_list() else { return rsx! { "loading breeds..." }; }; @@ -44,7 +44,7 @@ fn app() -> Element { #[component] fn BreedPic(breed: Signal) -> Element { - let fut = use_resource(move || async move { + let mut fut = use_resource(move || async move { reqwest::get(format!("https://dog.ceo/api/breed/{breed}/images/random")) .await .unwrap() @@ -52,14 +52,13 @@ fn BreedPic(breed: Signal) -> Element { .await }); - match fut.value().read().as_ref() { + match fut.read().as_ref() { Some(Ok(resp)) => rsx! { - div { - button { onclick: move |_| fut.restart(), "Click to fetch another doggo" } - img { max_width: "500px", max_height: "500px", src: "{resp.message}" } - } + button { onclick: move |_| fut.restart(), "Click to fetch another doggo" } + img { max_width: "500px", max_height: "500px", src: "{resp.message}" } }, - _ => rsx! { "loading image..." }, + Some(Err(_)) => rsx! { "loading image failed" }, + None => rsx! { "loading image..." }, } } diff --git a/examples/suspense.rs b/examples/suspense.rs index fec880751..2fa9757fe 100644 --- a/examples/suspense.rs +++ b/examples/suspense.rs @@ -50,7 +50,7 @@ fn app() -> Element { /// Suspense is achieved my moving the future into only the component that /// actually renders the data. fn Doggo() -> Element { - let fut = use_future(move || async move { + let mut fut = use_resource(move || async move { #[derive(serde::Deserialize)] struct DogApi { message: String, @@ -63,7 +63,7 @@ fn Doggo() -> Element { .await }); - match fut.value().read().as_ref() { + match fut.read().as_ref() { Some(Ok(resp)) => rsx! { button { onclick: move |_| fut.restart(), "Click to fetch another doggo" } div { img { max_width: "500px", max_height: "500px", src: "{resp.message}" } } diff --git a/packages/hooks/src/use_resource.rs b/packages/hooks/src/use_resource.rs index 4ac74fa44..222b62e7e 100644 --- a/packages/hooks/src/use_resource.rs +++ b/packages/hooks/src/use_resource.rs @@ -2,7 +2,7 @@ use crate::{use_callback, use_signal, UseCallback}; use dioxus_core::{ - prelude::{spawn, suspend, use_hook}, + prelude::{spawn, use_hook}, Task, }; use dioxus_signals::*; @@ -39,7 +39,7 @@ where // Set the value and state state.set(UseResourceState::Ready); - value.set(Some(Signal::new(res))); + value.set(Some(res)); }) }); @@ -70,7 +70,7 @@ where #[allow(unused)] pub struct Resource { - value: Signal>>, + value: Signal>, task: Signal, state: Signal, callback: UseCallback, @@ -148,17 +148,15 @@ impl Resource { } /// Get the current value of the future. - pub fn value(&self) -> Option> { - self.value.peek().as_ref().map(|sig| (*sig).into()) - } - - /// Wait for this async memo to resolve, returning the inner signal value - /// If the value is pending, returns none and suspends the current component - pub fn suspend(&self) -> Option> { - let out = self.value.cloned(); - if out.is_none() { - suspend(); - } - out.map(|sig| sig.into()) + pub fn value(&self) -> ReadOnlySignal> { + self.value.into() + } +} + +impl std::ops::Deref for Resource { + type Target = Signal>; + + fn deref(&self) -> &Self::Target { + &self.value } }