leptos-rs / leptos

Build fast web applications with Rust.
https://leptos.dev
MIT License
15.28k stars 599 forks source link

Error during hydration of a recursive component #2612

Open njust opened 1 month ago

njust commented 1 month ago

Describe the bug A recursive component like this:

#[component]
fn NestedArgs(cnt: u64) -> impl IntoView {
    let load_data = create_blocking_resource(move || cnt, data_fn);
    view! {
        <div>
            <Suspense fallback=move || {
                view! { Loading }
            }>
                {move || {
                    load_data
                        .and_then(|_| {
                            let mut views = vec![];
                            if cnt <= 3 {
                                let list = (0..cnt)
                                    .into_iter()
                                    .fold(
                                        ul(),
                                        |list, i| {
                                            let el = view! {
                                                <li>
                                                    <div>{cnt} - {i}</div>
                                                    <NestedArgs cnt=cnt + 1/>
                                                </li>
                                            }
                                                .into_view();
                                            list.child(el)
                                        },
                                    );
                                views.push(list.into_view());
                            }
                            views
                        })
                }}

            </Suspense>
        </div>
    }
}

Fails to hydrate with an error:

panicked at C:\Users\nico\.cargo\registry\src\index.crates.io-6f17d22bba15001f\leptos_dom-0.6.12\src\html.rs:1546:13:
assertion `left == right` failed: SSR and CSR elements have the same hydration key but different node kinds. Check out the docs for information about this kind of hydration bug: https://leptos-rs.github.io/leptos/ssr/24_hydration_bugs.html
  left: "UL"
 right: "DIV"

Stack:

__wbg_get_imports/imports.wbg.__wbg_new_abda76e883ba8a5f@http://localhost:3000/pkg/issue-repro.js:490:13
issue_repro.wasm.console_error_panic_hook::Error::new::hd8c81b3473190b07@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[7696]:0x3dcf5e
issue_repro.wasm.console_error_panic_hook::hook_impl::hfb98adbe1aed3422@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[1960]:0x2d1854
issue_repro.wasm.console_error_panic_hook::hook::h2c3497de43202b2d@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[10435]:0x40b559
issue_repro.wasm.core::ops::function::Fn::call::h39c7ed94ad2131f6@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[9260]:0x3fa35b
issue_repro.wasm.std::panicking::rust_panic_with_hook::h863c3a51a11f4e72@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[3920]:0x35a89a
issue_repro.wasm.std::panicking::begin_panic_handler::{{closure}}::h05155bb538a1bd9d@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[5084]:0x390ec4
issue_repro.wasm.std::sys_common::backtrace::__rust_end_short_backtrace::h71c22f1905bc7a46@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[12444]:0x41ebfb
issue_repro.wasm.rust_begin_unwind@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[9804]:0x402b65
issue_repro.wasm.core::panicking::panic_fmt::hbb51bfcb6582c8f7@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[10320]:0x409dfb
issue_repro.wasm.core::panicking::assert_failed_inner::h5c00984beaaabe27@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[1962]:0x2d1c94
issue_repro.wasm.core::panicking::assert_failed::hd400abfdd7d4a84a@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[6929]:0x3cb097
issue_repro.wasm.leptos_dom::html::create_leptos_element::h81145bef3be0af27@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[557]:0x1dc3e9
issue_repro.wasm.<leptos_dom::html::Div as core::default::Default>::default::h3185c68ecd039aa5@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[3149]:0x32d66e
issue_repro.wasm.leptos_dom::html::div::h9428a0f750902959@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[400]:0x17d6d8
issue_repro.wasm.issue_repro::app::__NestedArgs::ha729acc661cdd078@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[802]:0x22a626
issue_repro.wasm.issue_repro::app::NestedArgs::{{closure}}::h78c34f2c7f8e84ac@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[10174]:0x407e2e
issue_repro.wasm.<leptos_dom::components::Component<F,V> as leptos_dom::IntoView>::into_view::{{closure}}::h6a116b4609679311@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[373]:0x1644ce
issue_repro.wasm.leptos_reactive::runtime::RuntimeId::untrack::{{closure}}::hc225867f61dc2916@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[2769]:0x313e15
issue_repro.wasm.leptos_reactive::runtime::with_runtime::{{closure}}::h06e751bd0b5bf3ca@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[8669]:0x3f0205
issue_repro.wasm.std::thread::local::LocalKey<T>::try_with::hb739e9f598ed060f@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[3271]:0x3352a6
issue_repro.wasm.std::thread::local::LocalKey<T>::with::h031f094beadc4bdc@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[3253]:0x33403c
issue_repro.wasm.<leptos_dom::components::Component<F,V> as leptos_dom::IntoView>::into_view::hd40f4a5676188e2e@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[209]:0x74eff
issue_repro.wasm.<Func as leptos::ComponentConstructor<P>>::construct::h167865606e232179@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[6588]:0x3c2086
issue_repro.wasm.leptos::component_view::heb8c2ffe0fbee625@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[9493]:0x3fde21
issue_repro.wasm.issue_repro::app::__NestedArgs::{{closure}}::{{closure}}::{{closure}}::{{closure}}::{{closure}}::hab57f0dfa32bd738@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[292]:0x10a625
issue_repro.wasm.core::iter::traits::iterator::Iterator::fold::h370c5730288194ea@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[526]:0x1ce846
issue_repro.wasm.issue_repro::app::__NestedArgs::{{closure}}::{{closure}}::{{closure}}::{{closure}}::ha58bd8826456b9eb@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[364]:0x15b6e4
issue_repro.wasm.core::result::Result<T,E>::map::h0ec568e9b4b36f1b@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[4082]:0x3630dc
issue_repro.wasm.leptos_reactive::resource::Resource<S,core::result::Result<T,E>>::and_then::{{closure}}::h3062faba23dcb1bc@http://localhost:3000/pkg/issue-repro.wasm:wasm-function[5936]:0x3aefc7

image

Leptos Dependencies

leptos = { version = "0.6", features = ["nightly"] }
leptos_axum = { version = "0.6", optional = true }
leptos_meta = { version = "0.6", features = ["nightly"] }
leptos_router = { version = "0.6", features = ["nightly"] }

To Reproduce A minimal example which reproduces this issue can be found here: https://github.com/njust/leptos_hydration_issue

Expected behavior No error during hydration

gbj commented 1 month ago

In part, this is a (known but hard to fix) bug with nested Suspense and resources.

In part, this is an anti-pattern you should avoid if it is at all possible. Specifically, you should hoist all data-loading as high as possible in the application. Loading data in the way you're doing it creates a waterfall and prevents anything from running concurrently -- each component needs to wait for the previous component to finish loading before it even begins loading.