Seed: How to use setInterval?

Created on 31 Dec 2018  路  5Comments  路  Source: seed-rs/seed

First off, this is a pretty cool Rust web framework! 馃憤


I was playing with the quickstart repo, and tried to add a setInterval example:

https://github.com/dashed/seed-quickstart/blob/70b3f2c76e5d205b06adb4734cfcc1a08f412c5c/src/lib.rs#L42-L57

fn view(state: seed::App<Msg, Model>, model: Model) -> El<Msg> {

    let callback = Closure::wrap(Box::new(move || {
        state.update(Msg::Increment);
    }) as Box<dyn Fn()>);

    div![
        did_mount(move |_| {
            let window = web_sys::window().unwrap();
            window
                .set_interval_with_callback_and_timeout_and_arguments_0(
                    // Note this method call, which uses `as_ref()` to get a `JsValue`
                    // from our `Closure` which is then converted to a `&Function`
                    // using the `JsCast::unchecked_ref` function.
                    callback.as_ref().unchecked_ref(),
                    1_000,
                )
                .unwrap();
        }),
        button![
            simple_ev("click", Msg::Increment),
            format!("Hello, World 脳 {}", model.val)
        ]
    ]
}

But I'm getting this error:

screen shot 2018-12-31 at 12 39 55 pm

I'm pretty much new to WASM, and I'm unsure how to debug this 馃槥; I'm hoping if there's some guidance to this.

bug

Most helpful comment

This will work in the next version:

fn view(state: seed::App<Msg, Model>, model: Model) -> El<Msg> {  
    div![
        did_mount(move |_| {
            let state2 = state.clone();
            let callback = move || {
                state2.update(Msg::Increment);
            };
            seed::set_interval(Box::new(callback), 1000);
        }),

        button![
            simple_ev("click", Msg::Increment),
            format!("Hello, World 脳 {}", model.val)
        ]
    ]
}

My intent is to make things like this easy by providing a high-level API. The raw wasm-bindgen code your sample was based on's not something I'd like anyone to have to use.

All 5 comments

This is a bug in the framework - I'll update once fixed.

I got this working with a refactoring of your view func:

fn view(state: seed::App<Msg, Model>, model: Model) -> El<Msg> {  
    div![
        did_mount(move |_| {
            let state2 = state.clone();

            let callback = Closure::wrap(Box::new(move || {
                state2.update(Msg::Increment);
            }) as Box<dyn Fn()>);

            let window = web_sys::window().unwrap();
            window
                .set_interval_with_callback_and_timeout_and_arguments_0(
                    // Note this method call, which uses `as_ref()` to get a `JsValue`
                    // from our `Closure` which is then converted to a `&Function`
                    // using the `JsCast::unchecked_ref` function.
                    callback.as_ref().unchecked_ref(),
                    1_000,
                )
                .unwrap();
                callback.forget();
        }),
        button![
            simple_ev("click", Msg::Increment),
            format!("Hello, World 脳 {}", model.val)
        ]
    ]
}

The key differences are moving the callback into the did_mount closure, using a clone of state to avoid closure/moving problems, and forgetting the callback. I'm not sure if the best approach here is to make a change in the library to facilitate doing things like this, or to update the docs.

This will work in the next version:

fn view(state: seed::App<Msg, Model>, model: Model) -> El<Msg> {  
    div![
        did_mount(move |_| {
            let state2 = state.clone();
            let callback = move || {
                state2.update(Msg::Increment);
            };
            seed::set_interval(Box::new(callback), 1000);
        }),

        button![
            simple_ev("click", Msg::Increment),
            format!("Hello, World 脳 {}", model.val)
        ]
    ]
}

My intent is to make things like this easy by providing a high-level API. The raw wasm-bindgen code your sample was based on's not something I'd like anyone to have to use.

@David-OConnor Oh awesome! Thanks for looking into this. 馃憤 I was unaware of the forget() function.

Published in v0.2.2

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MartinKavik picture MartinKavik  路  4Comments

TuntematonSotilas picture TuntematonSotilas  路  3Comments

David-OConnor picture David-OConnor  路  4Comments

sbditto85 picture sbditto85  路  3Comments

matiu2 picture matiu2  路  5Comments