chinedufn / percy

Build frontend browser apps with Rust + WebAssembly. Supports server side rendering.
https://chinedufn.github.io/percy/
Apache License 2.0
2.26k stars 84 forks source link

Isomorphic example – Click counter not incremented on click #121

Closed murtyjones closed 5 years ago

murtyjones commented 5 years ago

The click counter doesn't increment in the post-Rocket version of the isomorphic web app example.

click_counter

Here's the error text:

isomorphic_client.js:1269 Uncaught Error: expected a number argument
    at _assertNum (isomorphic_client.js:1269)
    at Function.cb (isomorphic_client.js:1279)
chinedufn commented 5 years ago

Fixed https://github.com/chinedufn/percy/commit/161d900ac58142b48d344acbe8933fd4e9d0d270

This is good reason to start moving towards a more type safe html! procedural macro where we don't even let you use the wrong types for things.

For example, when we're parsing the arguments for closures we could/should verify that if.. say.. your attribute is onclick then your closure should have one parameter with type web_sys::MouseEvent .. or something like that..

https://github.com/chinedufn/percy/blob/4ba60b55ab9372fb9b8e8b03dfe2137c932f4be0/crates/html-macro/src/parser/open_tag.rs#L29-L37

Anyways .. that's future work..

Thanks for reporting!!!!!

murtyjones commented 5 years ago

Makes sense! Thanks the insight.

As another alternative future possibility, allowing a closure to be defined outside of the !html macro could allow the built in type safety to evaluate the closure and all the developer has to remember is to pass in the the event:

let click_handler = move |_: web_sys::Event| store.borrow_mut().msg(&Msg::Click);

        html! {
        <div>

          { nav_bar }

          <span> The button has been clicked: { click_component } times! </span>
          <button onclick={ |e| click_handler(e) }>

Just a thought for the future!

chinedufn commented 5 years ago

allowing a closure to be defined outside of the !html macro could allow the built in type safety to evaluate the closure

Unless I'm missing something - this doesn't seem true.


wasm-bindgen has a Closure and js_sys has a Function type.

You combine these to create a type that you can use to .add_event_listener on an element.

For example .. here's where we store events in our VirtualNode type

https://github.com/chinedufn/percy/blob/4ba60b55ab9372fb9b8e8b03dfe2137c932f4be0/crates/virtual-node/src/lib.rs#L574-L580


Procedural macros get compiled into real code. So to say that moving code outside of a macro is to say that the macro must be doing something to the code to change it. (which is totally possible and useful in many cases!)

The html! doesn't do that - so there's no difference in moving the closure outside.


The reason there is no compile time error is because we're storing these closures dynamically (as shown in the above link). So .. right now any type is completely valid regardless of the event.

If we didn't do this we'd need to have a field for every single possible type of closure. This isn't feasible. We need dynamism here.

The trade-off is a compromise in type safety.

But you can squash that trade-off completely by making your procedural macro enforce types. i.e. .. if onclick -> make sure parameter is a mouse event


So - in short - I don't think that that is a future alternative. But let me know if I'm missing something that you're saying!

chinedufn commented 5 years ago

The html-validation create is meant the be the underpinning of a lot of this type of compile time validation going forwards. https://github.com/chinedufn/percy/blob/master/crates/html-validation/src/lib.rs