Skip to content

Commit

Permalink
Merge pull request #1758 from leptos-rs/sus2
Browse files Browse the repository at this point in the history
Fix Suspense issues on subsequent navigations
  • Loading branch information
gbj authored Sep 20, 2023
2 parents 1759a3e + f85bfd3 commit 726cf47
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 53 deletions.
30 changes: 16 additions & 14 deletions leptos/src/suspense_component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ use leptos_dom::{DynChild, HydrationCtx, IntoView};
use leptos_macro::component;
#[cfg(any(feature = "csr", feature = "hydrate"))]
use leptos_reactive::SignalGet;
#[allow(unused)]
use leptos_reactive::{
create_memo, provide_context, run_as_child, SignalGetUntracked,
SuspenseContext,
create_memo, provide_context, SignalGetUntracked, SuspenseContext,
};
#[cfg(not(any(feature = "csr", feature = "hydrate")))]
use leptos_reactive::{with_owner, Owner, SharedContext};
Expand Down Expand Up @@ -77,6 +75,16 @@ where
let owner =
Owner::current().expect("<Suspense/> created with no reactive owner");

// provide this SuspenseContext to any resources below it
// run in a memo so the children are children of this parent
let children = create_memo({
let orig_children = Rc::clone(&orig_children);
move |_| {
provide_context(context);
orig_children().into_view()
}
});

// likewise for the fallback
let fallback = create_memo({
move |_| {
Expand All @@ -92,20 +100,13 @@ where

let child = DynChild::new({
move || {
// provide this SuspenseContext to any resources below it
// run in a memo so the children are children of this parent
let children = run_as_child({
let orig_children = Rc::clone(&orig_children);
move || {
provide_context(context);
orig_children().into_view()
}
});
// pull lazy memo before checking if context is ready
let children_rendered = children.get_untracked();

#[cfg(any(feature = "csr", feature = "hydrate"))]
{
if ready.get() {
children
children_rendered
} else {
fallback.get_untracked()
}
Expand All @@ -122,7 +123,8 @@ where
if context.pending_resources.get() == 0 {
with_owner(owner, move || {
//HydrationCtx::continue_from(current_id);
DynChild::new(move || children.clone()).into_view()
DynChild::new(move || children_rendered.clone())
.into_view()
})
}
// show the fallback, but also prepare to stream HTML
Expand Down
6 changes: 3 additions & 3 deletions leptos/src/transition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use leptos_dom::{Fragment, HydrationCtx, IntoView, View};
use leptos_macro::component;
use leptos_reactive::{
create_isomorphic_effect, create_rw_signal, use_context, RwSignal,
SignalGet, SignalSet, SignalSetter, SuspenseContext,
SignalGet, SignalGetUntracked, SignalSet, SignalSetter, SuspenseContext,
};
use std::{
cell::{Cell, RefCell},
Expand Down Expand Up @@ -125,7 +125,7 @@ where
let suspense_context = held_suspense_context.borrow().unwrap();

if cfg!(feature = "hydrate")
|| !first_run.get()
|| !first_run.get_untracked()
|| (cfg!(feature = "csr") && first_run.get())
{
*prev_children.borrow_mut() = Some(frag.clone());
Expand Down Expand Up @@ -161,7 +161,7 @@ fn is_first_run(
false
} else {
match (
first_run.get(),
first_run.get_untracked(),
cfg!(feature = "hydrate"),
suspense_context.has_local_only(),
) {
Expand Down
4 changes: 2 additions & 2 deletions leptos_reactive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ pub use resource::*;
use runtime::*;
pub use runtime::{
as_child_of_current_owner, batch, create_runtime, current_runtime,
on_cleanup, run_as_child, set_current_runtime, untrack,
untrack_with_diagnostics, with_current_owner, with_owner, Owner, RuntimeId,
on_cleanup, set_current_runtime, untrack, untrack_with_diagnostics,
with_current_owner, with_owner, Owner, RuntimeId,
};
pub use selector::*;
pub use serialization::*;
Expand Down
34 changes: 0 additions & 34 deletions leptos_reactive/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -782,40 +782,6 @@ where
}
}

/// Runs the given function as a child of the current Owner, once.
pub fn run_as_child<T>(f: impl FnOnce() -> T + 'static) -> T {
let owner = with_runtime(|runtime| runtime.owner.get())
.expect("runtime should be alive when created");
let (value, disposer) = with_runtime(|runtime| {
let prev_observer = runtime.observer.take();
let prev_owner = runtime.owner.take();

runtime.owner.set(owner);
runtime.observer.set(owner);

let id = runtime.nodes.borrow_mut().insert(ReactiveNode {
value: None,
state: ReactiveNodeState::Clean,
node_type: ReactiveNodeType::Trigger,
});
runtime.push_scope_property(ScopeProperty::Trigger(id));
let disposer = Disposer(id);

runtime.owner.set(Some(id));
runtime.observer.set(Some(id));

let v = f();

runtime.observer.set(prev_observer);
runtime.owner.set(prev_owner);

(v, disposer)
})
.expect("runtime should be alive when run");
on_cleanup(move || drop(disposer));
value
}

/// Wraps the given function so that, whenever it is called, it is run
/// in the reactive scope of whatever the reactive owner was when it was
/// created.
Expand Down

0 comments on commit 726cf47

Please sign in to comment.