-
-
Notifications
You must be signed in to change notification settings - Fork 821
Description
EDIT: There was some error in my reproduction, this is now fixed.
Describe the bug
It is expected that the Transition component will not switch to its fallback state once all the resources in it have loaded once.
However, there is an edge case that I have been encountering: If the initial load on the Transition doesn't subscribe to any resources, (i.e. it resolves without ever going into the fallback state), then it will not fully be marked as "resolved." If a signal then causes the Transition to subscribe to a new resource, then it will move back into fallback state. Note this only happens once - the Transition is still correctly ensuring that it never goes into fallback more than once. It also doesn't happen for SSR rendered transitions.
Leptos Dependencies
leptos = { version = "0.7.8", features = ["nightly"] }
leptos_meta = { version = "0.7.8" }
leptos_actix = { version = "0.7.8", optional = true }
leptos_router = { version = "0.7.8", features = ["nightly"] }To Reproduce
Click the "Switch" button in order to render the Transition component on the client side, then click the "Switch to async" button. You will see that the Transition switches into fallback state the moment the button is being pressed.
#[component]
fn HomePage() -> impl IntoView {
let s_res = StoredValue::new(None::<ArcLocalResource<&'static str>>);
let toggle = RwSignal::new(false);
let is_async_mode = RwSignal::new(false);
let dragon = move || {
if !is_async_mode.get() {
"Safi'jiiva"
} else {
let r = s_res.get_value();
let res = r.unwrap_or_else(|| {
let res = ArcLocalResource::new(|| async {
async_std::task::sleep(Duration::from_millis(1000)).await;
"The Ur-Dragon"
});
s_res.set_value(Some(res.clone()));
res
});
res.get()
.map(|s| *s)
.unwrap_or("The Ur-Dragon is coming...")
}
};
let contents = move || {
if toggle.get() {
let fallback = move || {
logging::log!("Fallback rendered...");
"Loading..."
};
let toggle_async_mode = move |_| {
is_async_mode.update(|v| *v = !*v);
};
let async_toggle_label = move || match is_async_mode.get() {
true => "Switch to const",
false => "Switch to async",
};
view! {
<button on:click=toggle_async_mode>{async_toggle_label}</button>
<Transition fallback>
<h1>{dragon}</h1>
</Transition>
}
.into_any()
} else {
view! {
"Toggled off"
}
.into_any()
}
};
view! {
<div>
<button on:click=move |_| toggle.update(|v| *v = !*v)>"Switch"</button>
{contents}
</div>
}
}Next Steps
[ ] I will make a PR
[ ] I would like to make a PR, but need help getting started
[x] I want someone else to take the time to fix this
[ ] This is a low priority for me and is just shared for your information
In my app, I might work around this issue by simply not using LocalResource at all, which I can do because I am never doing anything with Suspense or fallback states (all my SSR stuff is blocking). However for other future apps I write (and possibly future features on this app, although unlikely) this might become a problem. Since it currently only results in a mildly annoying flicker, and I have other more important tasks to complete, I will wait a few weeks before implementing my workaround, in case someone else finds the time to resolve this.