Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

create_resource + <Router> + <Transition> infinite loop bug #1629

Closed
sebadob opened this issue Sep 2, 2023 · 0 comments
Closed

create_resource + <Router> + <Transition> infinite loop bug #1629

sebadob opened this issue Sep 2, 2023 · 0 comments
Labels
bug Something isn't working

Comments

@sebadob
Copy link
Contributor

sebadob commented Sep 2, 2023

Describe the bug
Since the v0.5.0-beta2 (I guess, I never had this problem before) I am experiencing a very annoying bug.
You need the following situation:

  1. SSR setup with axum (don't know if it happens with actix too)
  2. Leptos Router set up
  3. Fetch data in multiple resources from ServerFn's
  4. Read these resources in the same <Transition> block
  5. Finally, get stuck in an inifite loop which crashes the browser when you switch to that route during CSR

Leptos Dependencies
Use the start-axum example as the base with leptos v0.5.0-beta2

To Reproduce
I created a minimal example based on the start-axum template which creates this bug for me every time.
Basically, just paste the code into the app.rs. Everything is perfectly fine when you just hit F5 / refresh multiple times on both routes. My browser fully crashes each time, when I render the page and then navigate to Page 1 after the hydration on the client side has finished.

You can see it easily if you just pull up a sys monitor and notice that 1 core is being utilized 100% all of the time, until the browser notifies me that the script is broken and I should kill it manually. During this time, everything inside the Transition block is being re-rendered as fast as the CPU can. This does not have any impact on the server side (I tested this with running the backend on another host), this happens only inside the browser.

As soon as you out-comment one of the resource .get()s, this does not happen any more.
Another solution is to wrap a second <Transition> inside the first one. I don't know if this is the basic idea, that each resource read should be wrapped in its own transition or not, I never had this problem before. I am not sure if it is linked to the beta2 release.

use leptos::*;
use leptos_router::*;

#[server]
pub async fn access_server() -> Result<String, ServerFnError> {
    Ok("Hi from Server".to_string())
}

#[server]
pub async fn access_server_second() -> Result<String, ServerFnError> {
    Ok("Hi No. 2 from Server".to_string())
}

#[component]
pub fn App() -> impl IntoView {
    view! {
        <Router fallback=|| "err".into_view()>
            <nav>
                <A href="">"Page 1"</A>
                <A href="/page2">"Page 2"</A>
            </nav>
            <Routes>
                <Route path="" view=|| view! { <Page1/> } />
                <Route path="/page2" view=|| view! { <Page2/> } />
            </Routes>
        </Router>
    }
}

#[component]
pub fn Page1() -> impl IntoView {
    let res = create_resource(|| (), move |_| async move { access_server().await });
    let res_2 = create_resource(|| (), move |_| async move { access_server_second().await });

    view! {
        <Transition fallback=|| ()>
            <h1>"Page 1 with resources"</h1>
            <p>
                "This page loads fine when SSR, but but can make the browser go into \
                an infinite loop when switching routes and this route is being CSR"
            </p>
            <p>
                "This only happens, when we have more than 1 resource inside the transition, \
                which happens quite often in more complex UIs."
            </p>
            <p>
                "The problem is gone as soon as you just out-comment one of the below resource get()'s"
            </p>
            { move || res.get().map(|r| r.unwrap_or_default()) }
            { move || res_2.get().map(|r| r.unwrap_or_default()) }
        </Transition>
    }
}

#[component]
pub fn Page2() -> impl IntoView {
    view! { <h1>"Page 2"</h1> }
}

Expected behavior
Not having the browser crash each time.

EDIT:
In this example of course it would be a no brainer to just have 2 Transitions (even though it would be tedious). I stumbled acros this problem a few times now, when I basically have a main component which does some data fetching from various resources and then I want to use that data in multiple sub-components. To get around this, I always have to create an "in-between-component" which then wraps these values either into signals or stored values, which is a lot of additional code as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants