Final Suspense fix?

This commit is contained in:
Greg Johnston 2022-12-23 11:40:57 -05:00
parent 6354b79588
commit 590ec40e0c
5 changed files with 33 additions and 23 deletions

View file

@ -1,8 +1,10 @@
use cfg_if::cfg_if;
use leptos_macro::component;
use std::rc::Rc;
use leptos_dom::{DynChild, Fragment, HydrationCtx, IntoView, Component};
use leptos_dom::{DynChild, Fragment, IntoView, Component};
use leptos_reactive::{provide_context, Scope, SuspenseContext};
#[cfg(not(any(feature = "csr", feature = "hydrate")))]
use leptos_dom::{HydrationCtx, HydrationKey};
/// If any [Resources](leptos_reactive::Resource) are read in the `children` of this
/// component, it will show the `fallback` while they are loading. Once all are resolved,
@ -71,16 +73,15 @@ where
let orig_child = Rc::new(children);
Component::new("Suspense", move |cx| {
DynChild::new(move || {
let current_id = HydrationCtx::peek();
#[cfg(not(any(feature = "csr", feature = "hydrate")))]
let current_id = HydrationCtx::peek();
DynChild::new(move || {
cfg_if! {
if #[cfg(any(feature = "csr", feature = "hydrate"))] {
if context.ready() {
HydrationCtx::continue_from(current_id);
orig_child(cx).into_view(cx)
} else {
HydrationCtx::continue_from(current_id);
fallback().into_view(cx)
}
} else {
@ -95,10 +96,15 @@ where
// show the fallback, but also prepare to stream HTML
else {
let orig_child = Rc::clone(&orig_child);
cx.register_suspense(context, &current_id.to_string(), {
let current_id = current_id.clone();
let fragment_id = HydrationKey {
previous: current_id.previous,
offset: current_id.offset + 1
};
move || {
HydrationCtx::continue_from(current_id);
HydrationCtx::continue_from(fragment_id);
orig_child(cx)
.into_view(cx)
.render_to_string(cx)
@ -111,7 +117,7 @@ where
}
};
HydrationCtx::continue_from(current_id);
HydrationCtx::continue_from(current_id.clone());
initial
}

View file

@ -1,8 +1,10 @@
use cfg_if::cfg_if;
use leptos_dom::{Component, DynChild, Fragment, IntoView, HydrationCtx};
use leptos_dom::{Component, DynChild, Fragment, IntoView};
use leptos_macro::component;
use leptos_reactive::{provide_context, Scope, SignalSetter, SuspenseContext};
use std::{cell::RefCell, rc::Rc};
#[cfg(not(any(feature = "csr", feature = "hydrate")))]
use leptos_dom::{HydrationCtx, HydrationKey};
/// If any [Resource](leptos_reactive::Resource)s are read in the `children` of this
/// component, it will show the `fallback` while they are loading. Once all are resolved,
@ -84,14 +86,13 @@ where
let prev_child = RefCell::new(None);
Component::new("Transition", move |cx| {
DynChild::new(move || {
let current_id = HydrationCtx::peek();
#[cfg(not(any(feature = "csr", feature = "hydrate")))]
let current_id = HydrationCtx::peek();
DynChild::new(move || {
cfg_if! {
if #[cfg(any(feature = "csr", feature = "hydrate"))] {
if context.ready() {
leptos_dom::log!("showing reading view");
HydrationCtx::continue_from(current_id);
let current_child = orig_child(cx).into_view(cx);
*prev_child.borrow_mut() = Some(current_child.clone());
if let Some(pending) = &set_pending {
@ -99,14 +100,11 @@ where
}
current_child
} else if let Some(prev_child) = &*prev_child.borrow() {
leptos_dom::log!("holding current view {prev_child:?}");
if let Some(pending) = &set_pending {
pending.set(true);
}
prev_child.clone()
} else {
HydrationCtx::continue_from(current_id);
leptos_dom::log!("showing fallback view");
if let Some(pending) = &set_pending {
pending.set(true);
}
@ -128,8 +126,12 @@ where
let orig_child = Rc::clone(&orig_child);
cx.register_suspense(context, &current_id.to_string(), {
let current_id = current_id.clone();
let fragment_id = HydrationKey {
previous: current_id.previous,
offset: current_id.offset + 1
};
move || {
HydrationCtx::continue_from(current_id);
HydrationCtx::continue_from(fragment_id);
orig_child(cx)
.into_view(cx)
.render_to_string(cx)
@ -142,7 +144,7 @@ where
}
};
HydrationCtx::continue_from(current_id);
HydrationCtx::continue_from(current_id.clone());
initial
}

View file

@ -18,9 +18,12 @@ static mut IS_HYDRATING: LazyCell<bool> = LazyCell::new(|| {
return crate::document().get_element_by_id("_0-0-0").is_some();
});
/// A stable identifer within the server-rendering or hydration process.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct HydrationKey {
/// The key of the previous component.
pub previous: String,
/// The element offset within the current component.
pub offset: usize
}

View file

@ -24,8 +24,7 @@ pub use components::*;
pub use events::typed as ev;
pub use helpers::*;
pub use html::*;
pub use hydration::HydrationCtx;
use hydration::HydrationKey;
pub use hydration::{HydrationCtx, HydrationKey};
pub use js_sys;
use leptos_reactive::Scope;
pub use logging::*;

View file

@ -131,11 +131,11 @@ pub fn render_to_stream_with_prefix(
var start = document.getElementById("_{fragment_id}o");
var end = document.getElementById("_{fragment_id}c");
var range = new Range();
range.setStartBefore(start.nextSibling);
range.setEndAfter(end.previousSibling);
range.setStartBefore(start.nextSibling.nextSibling);
range.setEndAfter(end.previousSibling.previousSibling);
range.deleteContents();
var tpl = document.getElementById("{fragment_id}f");
end.parentNode.insertBefore(tpl.content.cloneNode(true), end);
end.parentNode.insertBefore(tpl.content.cloneNode(true), end.previousSibling);
</script>
"#
)