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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use setInterval? #16

Closed
dashed opened this issue Dec 31, 2018 · 5 comments
Labels
bug

Comments

@dashed
Copy link

@dashed dashed commented Dec 31, 2018

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.

@David-OConnor David-OConnor added the bug label Dec 31, 2018
@David-OConnor

This comment has been minimized.

Copy link
Member

@David-OConnor David-OConnor commented Jan 2, 2019

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

@David-OConnor

This comment has been minimized.

Copy link
Member

@David-OConnor David-OConnor commented Jan 5, 2019

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.

@David-OConnor

This comment has been minimized.

Copy link
Member

@David-OConnor David-OConnor commented Jan 5, 2019

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.

@dashed

This comment has been minimized.

Copy link
Author

@dashed dashed commented Jan 5, 2019

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

@David-OConnor

This comment has been minimized.

Copy link
Member

@David-OConnor David-OConnor commented Jan 7, 2019

Published in v0.2.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can鈥檛 perform that action at this time.