mirror of
https://github.com/leptos-rs/leptos.git
synced 2025-12-27 09:54:41 -05:00
fix: properly support concurrent loading without breaking changes to ChooseView
This commit is contained in:
@@ -145,10 +145,8 @@ where
|
||||
provide_context(url.clone());
|
||||
provide_context(Matched(ArcMemo::from(matched.clone())));
|
||||
|
||||
let data = view.data();
|
||||
|
||||
ScopedFuture::new(async move {
|
||||
OwnedView::new(view.choose(data).await)
|
||||
OwnedView::new(view.choose().await)
|
||||
})
|
||||
}));
|
||||
|
||||
@@ -301,16 +299,13 @@ where
|
||||
let view = OwnedView::new(
|
||||
if let Some(set_is_routing) = set_is_routing {
|
||||
set_is_routing.set(true);
|
||||
let value = AsyncTransition::run(|| {
|
||||
let data = view.data();
|
||||
view.choose(data)
|
||||
})
|
||||
.await;
|
||||
let value =
|
||||
AsyncTransition::run(|| view.choose())
|
||||
.await;
|
||||
set_is_routing.set(false);
|
||||
value
|
||||
} else {
|
||||
let data = view.data();
|
||||
view.choose(data).await
|
||||
view.choose().await
|
||||
},
|
||||
);
|
||||
|
||||
@@ -526,11 +521,7 @@ where
|
||||
provide_context(params_memo);
|
||||
provide_context(Matched(ArcMemo::from(matched)));
|
||||
|
||||
let data = view.data();
|
||||
|
||||
ScopedFuture::new(
|
||||
async move { view.choose(data).await },
|
||||
)
|
||||
ScopedFuture::new(async move { view.choose().await })
|
||||
})
|
||||
.now_or_never()
|
||||
.expect("async route used in SSR");
|
||||
@@ -712,10 +703,8 @@ where
|
||||
provide_context(url.clone());
|
||||
provide_context(Matched(ArcMemo::from(matched.clone())));
|
||||
|
||||
let data = view.data();
|
||||
|
||||
ScopedFuture::new(async move {
|
||||
OwnedView::new(view.choose(data).await)
|
||||
OwnedView::new(view.choose().await)
|
||||
})
|
||||
}));
|
||||
|
||||
@@ -810,10 +799,8 @@ where
|
||||
provide_context(url.clone());
|
||||
provide_context(Matched(ArcMemo::from(matched.clone())));
|
||||
|
||||
let data = view.data();
|
||||
|
||||
ScopedFuture::new(async move {
|
||||
OwnedView::new(view.choose(data).await)
|
||||
OwnedView::new(view.choose().await)
|
||||
})
|
||||
}));
|
||||
|
||||
|
||||
@@ -8,8 +8,7 @@ pub struct AnyChooseView {
|
||||
value: Erased,
|
||||
clone: fn(&Erased) -> AnyChooseView,
|
||||
#[allow(clippy::type_complexity)]
|
||||
choose: fn(Erased, Erased) -> Pin<Box<dyn Future<Output = AnyView>>>,
|
||||
data: fn(&Erased) -> Erased,
|
||||
choose: fn(Erased) -> Pin<Box<dyn Future<Output = AnyView>>>,
|
||||
preload: for<'a> fn(&'a Erased) -> Pin<Box<dyn Future<Output = ()> + 'a>>,
|
||||
}
|
||||
|
||||
@@ -27,12 +26,8 @@ impl AnyChooseView {
|
||||
|
||||
fn choose<T: ChooseView>(
|
||||
value: Erased,
|
||||
data: Erased,
|
||||
) -> Pin<Box<dyn Future<Output = AnyView>>> {
|
||||
value
|
||||
.into_inner::<T>()
|
||||
.choose(data.into_inner::<T::Data>())
|
||||
.boxed_local()
|
||||
value.into_inner::<T>().choose().boxed_local()
|
||||
}
|
||||
|
||||
fn preload<'a, T: ChooseView>(
|
||||
@@ -41,32 +36,21 @@ impl AnyChooseView {
|
||||
value.get_ref::<T>().preload().boxed_local()
|
||||
}
|
||||
|
||||
fn data<T: ChooseView>(value: &Erased) -> Erased {
|
||||
Erased::new(value.get_ref::<T>().data())
|
||||
}
|
||||
|
||||
Self {
|
||||
value: Erased::new(value),
|
||||
clone: clone::<T>,
|
||||
choose: choose::<T>,
|
||||
data: data::<T>,
|
||||
preload: preload::<T>,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ChooseView for AnyChooseView {
|
||||
type Data = Erased;
|
||||
|
||||
async fn choose(self, data: Self::Data) -> AnyView {
|
||||
(self.choose)(self.value, data).await
|
||||
async fn choose(self) -> AnyView {
|
||||
(self.choose)(self.value).await
|
||||
}
|
||||
|
||||
async fn preload(&self) {
|
||||
(self.preload)(&self.value).await;
|
||||
}
|
||||
|
||||
fn data(&self) -> Self::Data {
|
||||
(self.data)(&self.value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use either_of::*;
|
||||
use leptos::prelude::{ArcStoredValue, WriteValue};
|
||||
use std::{future::Future, marker::PhantomData};
|
||||
use tachys::view::any_view::{AnyView, IntoAny};
|
||||
|
||||
@@ -6,13 +7,9 @@ pub trait ChooseView
|
||||
where
|
||||
Self: Send + Clone + 'static,
|
||||
{
|
||||
type Data: Send + 'static;
|
||||
|
||||
fn choose(self, data: Self::Data) -> impl Future<Output = AnyView>;
|
||||
fn choose(self) -> impl Future<Output = AnyView>;
|
||||
|
||||
fn preload(&self) -> impl Future<Output = ()>;
|
||||
|
||||
fn data(&self) -> Self::Data;
|
||||
}
|
||||
|
||||
impl<F, View> ChooseView for F
|
||||
@@ -20,34 +17,26 @@ where
|
||||
F: Fn() -> View + Send + Clone + 'static,
|
||||
View: IntoAny,
|
||||
{
|
||||
type Data = ();
|
||||
|
||||
async fn choose(self, _data: ()) -> AnyView {
|
||||
async fn choose(self) -> AnyView {
|
||||
self().into_any()
|
||||
}
|
||||
|
||||
async fn preload(&self) {}
|
||||
|
||||
fn data(&self) -> Self::Data {}
|
||||
}
|
||||
|
||||
impl<T> ChooseView for Lazy<T>
|
||||
where
|
||||
T: LazyRoute,
|
||||
T: Send + Sync + LazyRoute,
|
||||
{
|
||||
type Data = T;
|
||||
|
||||
async fn choose(self, data: T) -> AnyView {
|
||||
async fn choose(self) -> AnyView {
|
||||
let data = self.data.write_value().take().unwrap_or_else(T::data);
|
||||
T::view(data).await
|
||||
}
|
||||
|
||||
async fn preload(&self) {
|
||||
*self.data.write_value() = Some(T::data());
|
||||
T::preload().await;
|
||||
}
|
||||
|
||||
fn data(&self) -> Self::Data {
|
||||
T::data()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LazyRoute: Send + 'static {
|
||||
@@ -63,11 +52,15 @@ pub trait LazyRoute: Send + 'static {
|
||||
#[derive(Debug)]
|
||||
pub struct Lazy<T> {
|
||||
ty: PhantomData<T>,
|
||||
data: ArcStoredValue<Option<T>>,
|
||||
}
|
||||
|
||||
impl<T> Clone for Lazy<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self { ty: self.ty }
|
||||
Self {
|
||||
ty: self.ty,
|
||||
data: self.data.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,20 +74,17 @@ impl<T> Default for Lazy<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
ty: Default::default(),
|
||||
data: ArcStoredValue::new(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ChooseView for () {
|
||||
type Data = ();
|
||||
|
||||
async fn choose(self, _data: ()) -> AnyView {
|
||||
async fn choose(self) -> AnyView {
|
||||
().into_any()
|
||||
}
|
||||
|
||||
async fn preload(&self) {}
|
||||
|
||||
fn data(&self) -> Self::Data {}
|
||||
}
|
||||
|
||||
impl<A, B> ChooseView for Either<A, B>
|
||||
@@ -102,15 +92,10 @@ where
|
||||
A: ChooseView,
|
||||
B: ChooseView,
|
||||
{
|
||||
type Data = Either<A::Data, B::Data>;
|
||||
|
||||
async fn choose(self, data: Self::Data) -> AnyView {
|
||||
match (self, data) {
|
||||
(Either::Left(f), Either::Left(d)) => f.choose(d).await.into_any(),
|
||||
(Either::Right(f), Either::Right(d)) => {
|
||||
f.choose(d).await.into_any()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
async fn choose(self) -> AnyView {
|
||||
match self {
|
||||
Either::Left(f) => f.choose().await.into_any(),
|
||||
Either::Right(f) => f.choose().await.into_any(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,13 +105,6 @@ where
|
||||
Either::Right(f) => f.preload().await,
|
||||
}
|
||||
}
|
||||
|
||||
fn data(&self) -> Self::Data {
|
||||
match self {
|
||||
Either::Left(f) => Either::Left(f.data()),
|
||||
Either::Right(f) => Either::Right(f.data()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! tuples {
|
||||
@@ -135,14 +113,11 @@ macro_rules! tuples {
|
||||
where
|
||||
$($ty: ChooseView,)*
|
||||
{
|
||||
type Data = $either<$($ty::Data),*>;
|
||||
|
||||
async fn choose(self, data: Self::Data) -> AnyView {
|
||||
match (self, data) {
|
||||
async fn choose(self) -> AnyView {
|
||||
match self {
|
||||
$(
|
||||
($either::$ty(f), $either::$ty(d)) => f.choose(d).await.into_any(),
|
||||
$either::$ty(f) => f.choose().await.into_any(),
|
||||
)*
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,12 +126,6 @@ macro_rules! tuples {
|
||||
$($either::$ty(f) => f.preload().await,)*
|
||||
}
|
||||
}
|
||||
|
||||
fn data(&self) -> Self::Data {
|
||||
match self {
|
||||
$($either::$ty(f) => $either::$ty(f.data()),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -692,7 +692,6 @@ where
|
||||
provide_context(params.clone());
|
||||
provide_context(url.clone());
|
||||
provide_context(matched.clone());
|
||||
let mut data = Some(view.data());
|
||||
view.preload().await;
|
||||
let child = outlet.child.clone();
|
||||
*view_fn.lock().or_poisoned() =
|
||||
@@ -707,8 +706,6 @@ where
|
||||
owner_where_used.with({
|
||||
let matched = matched.clone();
|
||||
|| {
|
||||
let data =
|
||||
data.take().unwrap_or_else(|| view.data());
|
||||
let child = child.clone();
|
||||
Suspend::new(Box::pin(async move {
|
||||
provide_context(child.clone());
|
||||
@@ -716,7 +713,7 @@ where
|
||||
provide_context(url.clone());
|
||||
provide_context(matched.clone());
|
||||
let view = SendWrapper::new(
|
||||
ScopedFuture::new(view.choose(data)),
|
||||
ScopedFuture::new(view.choose()),
|
||||
);
|
||||
let view = view.await;
|
||||
let view = MatchedRoute(
|
||||
@@ -855,6 +852,7 @@ where
|
||||
let child = outlet.child.clone();
|
||||
async move {
|
||||
let child = child.clone();
|
||||
view.preload().await;
|
||||
*view_fn.lock().or_poisoned() =
|
||||
Box::new(move |owner_where_used| {
|
||||
let prev_owner = route_owner
|
||||
@@ -879,18 +877,11 @@ where
|
||||
ScopedFuture::new(async move {
|
||||
if set_is_routing {
|
||||
AsyncTransition::run(
|
||||
|| {
|
||||
let data =
|
||||
view.data();
|
||||
view.choose(
|
||||
data,
|
||||
)
|
||||
},
|
||||
|| view.choose(),
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
let data = view.data();
|
||||
view.choose(data).await
|
||||
view.choose().await
|
||||
}
|
||||
})
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user