mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
Merge pull request #2986 from leptos-rs/2957
fix: get Suspend and ErrorBoundary working together correctly
This commit is contained in:
commit
e136c1fc44
2 changed files with 38 additions and 11 deletions
|
@ -4,7 +4,7 @@ use leptos_macro::component;
|
|||
use reactive_graph::{
|
||||
computed::ArcMemo,
|
||||
effect::RenderEffect,
|
||||
owner::Owner,
|
||||
owner::{provide_context, Owner},
|
||||
signal::ArcRwSignal,
|
||||
traits::{Get, Update, With, WithUntracked},
|
||||
};
|
||||
|
@ -13,6 +13,7 @@ use std::{fmt::Debug, marker::PhantomData, sync::Arc};
|
|||
use tachys::{
|
||||
html::attribute::Attribute,
|
||||
hydration::Cursor,
|
||||
reactive_graph::OwnedView,
|
||||
renderer::Renderer,
|
||||
ssr::StreamBuilder,
|
||||
view::{
|
||||
|
@ -96,17 +97,25 @@ where
|
|||
let hook = hook as Arc<dyn ErrorHook>;
|
||||
|
||||
let _guard = throw_error::set_error_hook(Arc::clone(&hook));
|
||||
let children = children.into_inner()();
|
||||
|
||||
ErrorBoundaryView {
|
||||
hook,
|
||||
boundary_id,
|
||||
errors_empty,
|
||||
children,
|
||||
errors,
|
||||
fallback,
|
||||
rndr: PhantomData,
|
||||
}
|
||||
let owner = Owner::new();
|
||||
let children = owner.with(|| {
|
||||
provide_context(Arc::clone(&hook));
|
||||
children.into_inner()()
|
||||
});
|
||||
|
||||
OwnedView::new_with_owner(
|
||||
ErrorBoundaryView {
|
||||
hook,
|
||||
boundary_id,
|
||||
errors_empty,
|
||||
children,
|
||||
errors,
|
||||
fallback,
|
||||
rndr: PhantomData,
|
||||
},
|
||||
owner,
|
||||
)
|
||||
}
|
||||
|
||||
struct ErrorBoundaryView<Chil, FalFn, Rndr> {
|
||||
|
|
|
@ -31,6 +31,7 @@ use std::{
|
|||
rc::Rc,
|
||||
sync::{Arc, Mutex, Weak},
|
||||
};
|
||||
use throw_error::ErrorHook;
|
||||
|
||||
/// A suspended `Future`, which can be used in the view.
|
||||
#[derive(Clone)]
|
||||
|
@ -177,6 +178,7 @@ where
|
|||
|
||||
// get a unique ID if there's a SuspenseContext
|
||||
let id = use_context::<SuspenseContext>().map(|sc| sc.task_id());
|
||||
let error_hook = use_context::<Arc<dyn ErrorHook>>();
|
||||
|
||||
// if the initial state was pending, spawn a future to wait for it
|
||||
// spawning immediately means that our now_or_never poll result isn't lost
|
||||
|
@ -185,6 +187,10 @@ where
|
|||
Executor::spawn_local({
|
||||
let state = Rc::clone(&inner);
|
||||
async move {
|
||||
let _guard = error_hook.as_ref().map(|hook| {
|
||||
throw_error::set_error_hook(Arc::clone(hook))
|
||||
});
|
||||
|
||||
let value = fut.as_mut().await;
|
||||
drop(id);
|
||||
Some(value).rebuild(&mut *state.borrow_mut());
|
||||
|
@ -192,6 +198,8 @@ where
|
|||
subscriber.forward();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
subscriber.forward();
|
||||
}
|
||||
|
||||
SuspendState { inner }
|
||||
|
@ -203,11 +211,16 @@ where
|
|||
// get a unique ID if there's a SuspenseContext
|
||||
let fut = inner;
|
||||
let id = use_context::<SuspenseContext>().map(|sc| sc.task_id());
|
||||
let error_hook = use_context::<Arc<dyn ErrorHook>>();
|
||||
|
||||
// spawn the future, and rebuild the state when it resolves
|
||||
Executor::spawn_local({
|
||||
let state = Rc::clone(&state.inner);
|
||||
async move {
|
||||
let _guard = error_hook
|
||||
.as_ref()
|
||||
.map(|hook| throw_error::set_error_hook(Arc::clone(hook)));
|
||||
|
||||
let value = fut.await;
|
||||
drop(id);
|
||||
// waiting a tick here allows Suspense to remount if necessary, which prevents some
|
||||
|
@ -368,6 +381,7 @@ where
|
|||
|
||||
// get a unique ID if there's a SuspenseContext
|
||||
let id = use_context::<SuspenseContext>().map(|sc| sc.task_id());
|
||||
let error_hook = use_context::<Arc<dyn ErrorHook>>();
|
||||
|
||||
// if the initial state was pending, spawn a future to wait for it
|
||||
// spawning immediately means that our now_or_never poll result isn't lost
|
||||
|
@ -376,6 +390,10 @@ where
|
|||
Executor::spawn_local({
|
||||
let state = Rc::clone(&inner);
|
||||
async move {
|
||||
let _guard = error_hook.as_ref().map(|hook| {
|
||||
throw_error::set_error_hook(Arc::clone(hook))
|
||||
});
|
||||
|
||||
let value = fut.as_mut().await;
|
||||
drop(id);
|
||||
Some(value).rebuild(&mut *state.borrow_mut());
|
||||
|
|
Loading…
Reference in a new issue