mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
feat: Suspend on style: and class:
This commit is contained in:
parent
6290c42159
commit
efd060c955
3 changed files with 116 additions and 9 deletions
|
@ -1,9 +1,10 @@
|
|||
use super::{ReactiveFunction, SharedReactiveFunction};
|
||||
use super::{ReactiveFunction, SharedReactiveFunction, Suspend};
|
||||
use crate::{html::class::IntoClass, renderer::DomRenderer};
|
||||
use any_spawner::Executor;
|
||||
use futures::FutureExt;
|
||||
use reactive_graph::{effect::RenderEffect, signal::guards::ReadGuard};
|
||||
use std::{
|
||||
borrow::{Borrow, Cow},
|
||||
ops::Deref,
|
||||
borrow::Borrow, cell::RefCell, future::Future, ops::Deref, rc::Rc,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
|
@ -692,3 +693,82 @@ mod stable {
|
|||
class_signal!(ArcMemo);
|
||||
class_signal!(ArcSignal);
|
||||
}
|
||||
|
||||
impl<Fut, Rndr> IntoClass<Rndr> for Suspend<Fut>
|
||||
where
|
||||
Fut: Clone + Future + Send + 'static,
|
||||
Fut::Output: IntoClass<Rndr>,
|
||||
Rndr: DomRenderer + 'static,
|
||||
{
|
||||
type AsyncOutput = Fut::Output;
|
||||
type State = Rc<RefCell<Option<<Fut::Output as IntoClass<Rndr>>::State>>>;
|
||||
type Cloneable = Self;
|
||||
type CloneableOwned = Self;
|
||||
|
||||
fn html_len(&self) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
fn to_html(self, style: &mut String) {
|
||||
if let Some(inner) = self.0.now_or_never() {
|
||||
inner.to_html(style);
|
||||
} else {
|
||||
panic!("You cannot use Suspend on an attribute outside Suspense");
|
||||
}
|
||||
}
|
||||
|
||||
fn hydrate<const FROM_SERVER: bool>(
|
||||
self,
|
||||
el: &<Rndr>::Element,
|
||||
) -> Self::State {
|
||||
let el = el.to_owned();
|
||||
let state = Rc::new(RefCell::new(None));
|
||||
Executor::spawn_local({
|
||||
let state = Rc::clone(&state);
|
||||
async move {
|
||||
*state.borrow_mut() =
|
||||
Some(self.0.await.hydrate::<FROM_SERVER>(&el));
|
||||
}
|
||||
});
|
||||
state
|
||||
}
|
||||
|
||||
fn build(self, el: &<Rndr>::Element) -> Self::State {
|
||||
let el = el.to_owned();
|
||||
let state = Rc::new(RefCell::new(None));
|
||||
Executor::spawn_local({
|
||||
let state = Rc::clone(&state);
|
||||
async move {
|
||||
*state.borrow_mut() = Some(self.0.await.build(&el));
|
||||
}
|
||||
});
|
||||
state
|
||||
}
|
||||
|
||||
fn rebuild(self, state: &mut Self::State) {
|
||||
Executor::spawn_local({
|
||||
let state = Rc::clone(&state);
|
||||
async move {
|
||||
let value = self.0.await;
|
||||
let mut state = state.borrow_mut();
|
||||
if let Some(state) = state.as_mut() {
|
||||
value.rebuild(state);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
self
|
||||
}
|
||||
|
||||
fn into_cloneable_owned(self) -> Self::CloneableOwned {
|
||||
self
|
||||
}
|
||||
|
||||
fn dry_resolve(&mut self) {}
|
||||
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self.0.await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use super::{ReactiveFunction, SharedReactiveFunction, Suspend};
|
||||
use crate::{html::style::IntoStyle, renderer::DomRenderer};
|
||||
use any_spawner::Executor;
|
||||
use futures::FutureExt;
|
||||
use reactive_graph::effect::RenderEffect;
|
||||
use std::{borrow::Cow, future::Future};
|
||||
use std::{borrow::Cow, cell::RefCell, future::Future, rc::Rc};
|
||||
|
||||
impl<F, S, R> IntoStyle<R> for (&'static str, F)
|
||||
where
|
||||
|
@ -432,7 +433,7 @@ where
|
|||
Rndr: DomRenderer + 'static,
|
||||
{
|
||||
type AsyncOutput = Fut::Output;
|
||||
type State = ();
|
||||
type State = Rc<RefCell<Option<<Fut::Output as IntoStyle<Rndr>>::State>>>;
|
||||
type Cloneable = Self;
|
||||
type CloneableOwned = Self;
|
||||
|
||||
|
@ -448,15 +449,41 @@ where
|
|||
self,
|
||||
el: &<Rndr>::Element,
|
||||
) -> Self::State {
|
||||
todo!()
|
||||
let el = el.to_owned();
|
||||
let state = Rc::new(RefCell::new(None));
|
||||
Executor::spawn_local({
|
||||
let state = Rc::clone(&state);
|
||||
async move {
|
||||
*state.borrow_mut() =
|
||||
Some(self.0.await.hydrate::<FROM_SERVER>(&el));
|
||||
}
|
||||
});
|
||||
state
|
||||
}
|
||||
|
||||
fn build(self, el: &<Rndr>::Element) -> Self::State {
|
||||
todo!()
|
||||
let el = el.to_owned();
|
||||
let state = Rc::new(RefCell::new(None));
|
||||
Executor::spawn_local({
|
||||
let state = Rc::clone(&state);
|
||||
async move {
|
||||
*state.borrow_mut() = Some(self.0.await.build(&el));
|
||||
}
|
||||
});
|
||||
state
|
||||
}
|
||||
|
||||
fn rebuild(self, state: &mut Self::State) {
|
||||
todo!()
|
||||
Executor::spawn_local({
|
||||
let state = Rc::clone(&state);
|
||||
async move {
|
||||
let value = self.0.await;
|
||||
let mut state = state.borrow_mut();
|
||||
if let Some(state) = state.as_mut() {
|
||||
value.rebuild(state);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
html::{attribute::Attribute, style::IntoStyle},
|
||||
html::attribute::Attribute,
|
||||
hydration::Cursor,
|
||||
renderer::Renderer,
|
||||
ssr::StreamBuilder,
|
||||
|
|
Loading…
Reference in a new issue