diff --git a/leptos_server/src/lib.rs b/leptos_server/src/lib.rs index dcf41f008..7d965efa7 100644 --- a/leptos_server/src/lib.rs +++ b/leptos_server/src/lib.rs @@ -204,11 +204,11 @@ mod view_implementations { type State = RenderEffectState>; fn build(self) -> Self::State { - (move || Suspend(async move { self.await })).build() + (move || Suspend::new(async move { self.await })).build() } fn rebuild(self, state: &mut Self::State) { - (move || Suspend(async move { self.await })).rebuild(state) + (move || Suspend::new(async move { self.await })).rebuild(state) } } @@ -239,7 +239,7 @@ mod view_implementations { where Self::Output: RenderHtml, { - (move || Suspend(async move { self.await })).add_any_attr(attr) + (move || Suspend::new(async move { self.await })).add_any_attr(attr) } } @@ -258,7 +258,7 @@ mod view_implementations { } fn resolve(self) -> impl Future + Send { - (move || Suspend(async move { self.await })).resolve() + (move || Suspend::new(async move { self.await })).resolve() } fn to_html_with_buf( @@ -267,7 +267,7 @@ mod view_implementations { position: &mut Position, escape: bool, ) { - (move || Suspend(async move { self.await })) + (move || Suspend::new(async move { self.await })) .to_html_with_buf(buf, position, escape); } @@ -279,7 +279,7 @@ mod view_implementations { ) where Self: Sized, { - (move || Suspend(async move { self.await })) + (move || Suspend::new(async move { self.await })) .to_html_async_with_buf::(buf, position, escape); } @@ -288,7 +288,7 @@ mod view_implementations { cursor: &Cursor, position: &PositionState, ) -> Self::State { - (move || Suspend(async move { self.await })) + (move || Suspend::new(async move { self.await })) .hydrate::(cursor, position) } } diff --git a/reactive_graph/src/computed/async_derived/mod.rs b/reactive_graph/src/computed/async_derived/mod.rs index f44534b2d..06b616a5a 100644 --- a/reactive_graph/src/computed/async_derived/mod.rs +++ b/reactive_graph/src/computed/async_derived/mod.rs @@ -20,11 +20,13 @@ use std::{ pin_project! { /// A [`Future`] wrapper that sets the [`Owner`] and [`Observer`] before polling the inner /// `Future`. + #[derive(Clone)] + #[allow(missing_docs)] pub struct ScopedFuture { - owner: Option, - observer: Option, + pub owner: Option, + pub observer: Option, #[pin] - fut: Fut, + pub fut: Fut, } } diff --git a/tachys/src/reactive_graph/suspense.rs b/tachys/src/reactive_graph/suspense.rs index b1669a91f..47ba6c6d5 100644 --- a/tachys/src/reactive_graph/suspense.rs +++ b/tachys/src/reactive_graph/suspense.rs @@ -21,7 +21,14 @@ use std::{cell::RefCell, fmt::Debug, future::Future, pin::Pin, rc::Rc}; /// A suspended `Future`, which can be used in the view. #[derive(Clone)] -pub struct Suspend(pub Fut); +pub struct Suspend(pub ScopedFuture); // TODO probably shouldn't be pub + +impl Suspend { + /// Creates a new suspended view. + pub fn new(fut: Fut) -> Self { + Self(ScopedFuture::new(fut)) + } +} impl Debug for Suspend { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -69,7 +76,7 @@ where // poll the future once immediately // if it's already available, start in the ready state // otherwise, start with the fallback - let mut fut = Box::pin(ScopedFuture::new(self.0)); + let mut fut = Box::pin(self.0); let initial = fut.as_mut().now_or_never(); let initially_pending = initial.is_none(); let inner = Rc::new(RefCell::new(initial.build())); @@ -96,7 +103,7 @@ where fn rebuild(self, state: &mut Self::State) { // get a unique ID if there's a SuspenseContext - let fut = ScopedFuture::new(self.0); + let fut = self.0; let id = use_context::().map(|sc| sc.task_id()); // spawn the future, and rebuild the state when it resolves @@ -137,10 +144,19 @@ where Self::Output: RenderHtml, { let attr = attr.into_cloneable_owned(); - Suspend(Box::pin(async move { - let this = self.0.await; - this.add_any_attr(attr) - })) + let ScopedFuture { + owner, + observer, + fut, + } = self.0; + Suspend(ScopedFuture { + owner, + observer, + fut: Box::pin(async move { + let this = fut.await; + this.add_any_attr(attr) + }), + }) } } @@ -234,7 +250,7 @@ where // poll the future once immediately // if it's already available, start in the ready state // otherwise, start with the fallback - let mut fut = Box::pin(ScopedFuture::new(self.0)); + let mut fut = Box::pin(self.0); let initial = fut.as_mut().now_or_never(); let initially_pending = initial.is_none(); let inner = Rc::new(RefCell::new(