Skip to content

Calling suspense::use_future makes children use_effect hooks execution inconsistent. #3780

Open
@lowlevl

Description

@lowlevl

Problem
EDIT: This initially mentioned the leaflet library, but upon testing more, I ended up minimizing the example even further and getting rid of leaflet while still getting inconsistencies with suspense::use_future.

The use of suspense::use_future makes subsequent uses of use_effect execute before the DOM is updated, which is unexpected and inconsistent with the expected behavior.

Steps To Reproduce

  1. Use yew = { version = "0.21.0", features = ["csr"] } or yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] } and web-sys = { version = "0.3.76", features = ["HtmlElement"] }.
  2. Use this minimal example:
use yew::prelude::*;

fn main() {
    #[function_component]
    fn View() -> HtmlResult {
        // Un-commenting the following line makes the application panic on the `expect`.
        // yew::suspense::use_future(|| async {})?;

        use_effect(|| {
            web_sys::window()
                .unwrap()
                .document()
                .unwrap()
                .get_element_by_id("foo")
                .expect("Element `#foo` should be rendered when the `use_effect` hook is called.");
        });

        Ok(html! {
            <div id="foo"></div>
        })
    }

    #[function_component]
    fn App() -> Html {
        html! {<Suspense><View /></Suspense>}
    }

    yew::Renderer::<App>::new().render();
}
  1. Adding back the commented use_future call breaks the get_element_by_id call and makes the application panic.

Expected behavior
I may misunderstand the usage of use_effect, but from what I understand, it is analogous to the Component::rendered method, and I would expect the use_effect (or Component::rendered) hook to be executed after the DOM has been updated in all cases.
However when a suspension arises, the use_effect (or Component::rendered) hook seems to be executed before the updated DOM becomes available to the JS (web-sys in this case) context.

Debug tools logs

  • With the call to use_future commented: nothing (expected).
  • With the call to use_future un-commented: panics with,
panicked at src/main.rs:91:18:
Element `#foo` should be rendered when the `use_effect` hook is called.

Stack:

__wbg_get_imports/imports.wbg.__wbg_new_8a6f238a6ece86ea@http://0.0.0.0:8080/maap-66a67bc41865f4a6.js:420:21
maap-9136cacef662140e.wasm.__wbg_new_8a6f238a6ece86ea externref shim@http://0.0.0.0:8080/maap-66a67bc41865f4a6_bg.wasm:wasm-function[4516]:0x10e274
maap-9136cacef662140e.wasm.console_error_panic_hook::Error::new::hc724c5e5fa09d029@http://0.0.0.0:8080/maap-66a67bc41865f4a6_bg.wasm:wasm-function[2707]:0xf4373
maap-9136cacef662140e.wasm.console_error_panic_hook::hook_impl::h5ae464cddaa778d8@http://0.0.0.0:8080/maap-66a67bc41865f4a6_bg.wasm:wasm-function[671]:0x96e46
maap-9136cacef662140e.wasm.console_error_panic_hook::hook::h8d3226f2e8bba476@http://0.0.0.0:8080/maap-66a67bc41865f4a6_bg.wasm:wasm-function[4007]:0x10923a
maap-9136cacef662140e.wasm.core::ops::function::Fn::call::h69a48aa9a25ea0d5@http://0.0.0.0:8080/maap-66a67bc41865f4a6_bg.wasm:wasm-function[3325]:0xff9e8
m…
[maap-66a67bc41865f4a6.js:337:21](http://0.0.0.0:8080/maap-66a67bc41865f4a6.js)
Uncaught RuntimeError: unreachable executed
[maap-66a67bc41865f4a6_bg.wasm:1108023:1](http://0.0.0.0:8080/maap-66a67bc41865f4a6_bg.wasm)

Environment:

  • Yew version: 0.21.0 && master
  • Rust version: 1.83
  • Build tool: trunk
  • OS, if relevant: Ubuntu LTS (latest)
  • Browser and version, if relevant: Firefox 133.0.3 (latest at the time) && Vanadium 131.0.6778.135 (Chromium-based) on Android.

Questionnaire

  • I'm interested in fixing this myself but don't know where to start (and if it's not too much of a rabbit-hole :))
  • I would like to fix and I have a solution
  • I don't have time to fix this right now, but maybe later

Thanks for the awesome project by the way, it's a pleasure to do front-end in Rust 💯

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions