yew v0.11 Release Notes

Release Date: 2020-01-06 // over 4 years ago
  • ๐Ÿš€ This release aims to lay the groundwork for Yew component libraries and clean up the API for the ever elusive 1.0 release.

    Transition Guide

    ๐Ÿš€ This release comes with a lot of breaking changes. We understand it's a hassle to update projects but the Yew team felt it was necessary to rip a few bandaids off now as we approach a 1.0 release in the (hopefully) near future. To ease the transition, here's a guide which outlines the main refactoring you will need to do for your project. (Note: all of the changes are reflected in the many example projects if you would like a proper reference example)

    1. Callback syntax

    This is the main painful breaking change. It applies to both element listeners as well as Component callback properties. A good rule of thumb is that your components will now have to retain a ComponentLink to create callbacks on demand or initialize callbacks in your component's create() method.

    Before:

    struct MyComponent;
    
    enum Msg {
        Click,
    }
    
    impl Component for MyComponent {
        type Message = Msg;
        type Properties = ();
    
        fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self {
            MyComponent
        }
    
        fn update(&mut self, msg: Self::Message) -> ShouldRender {
            match msg {
                Msg::Click => true,
            }
        }
    
        fn view(&self) -> Html<Self> {
            // BEFORE: Callbacks were created implicitly from this closure syntax
            html! {
                <button onclick=|_| Msg::Click>{ "Click me!" }</button>
            }
        }
    }
    

    After:

    struct MyComponent {
      link: ComponentLink<Self>,
    }
    
    enum Msg {
        Click,
    }
    
    impl Component for MyComponent {
        type Message = Msg;
        type Properties = ();
    
        fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
            MyComponent { link }
        }
    
        fn update(&mut self, msg: Self::Message) -> ShouldRender {
            match msg {
                Msg::Click => true,
            }
        }
    
        fn view(&self) -> Html {
            // AFTER: Callbacks need to be explicitly created now
            let onclick = self.link.callback(|_| Msg::Click);
            html! {
                <button onclick=onclick>{ "Click me!" }</button>
            }
        }
    }
    

    If a closure has a parameter you will now need to specify the parameter's type. A tip for finding the appropriate type is to search Yew's repo for the HTML attribute the closure is assigned to.

    For example, onkeydown of <button>:

    let onkeydown = self.link.callback(|e: KeyDownEvent| {
        // ...
    });
    

    and

    html! {
        <button onkeydown=onkeydown type="button">
            { "button" }
        </button>
    }
    

    2. Method Renames

    It should be safe to do a project-wide find/replace for the following:

    • send_self( -> send_message(
    • send_back( -> callback(
    • response( -> respond(
    • โšก๏ธ AgentUpdate -> AgentLifecycleEvent

    These renames will probably require some more care:

    • fn handle( -> fn handle_input( (for Agent trait implementations)

    3. Drop Generic Types for Html<Self> -> Html

    :tada: We are pretty excited about this change! The generic type parameter was confusing and restrictive and is now a thing of the past!

    Before:

    impl Component for MyComponent {
        // ...
    
        fn view(&self) -> Html<Self> {
            html! { /* ... */ }
        }
    }
    

    After:

    impl Component for MyComponent {
        // ...
    
        fn view(&self) -> Html {
            html! { /* ... */ }
        }
    }
    

    ๐Ÿ‘ฏ 4. Properties must implement Clone

    ๐Ÿšš In yew v0.8 we removed the requirement that component properties implement Clone ๐Ÿš€ and in this release we are adding the requirement again. This change is needed to improve the ergonomics of nested components. The only time properties will be ๐Ÿ‘ฏ cloned is when a wrapper component re-renders nested children components.

    • โšก๏ธ Features

      • Added html_nested! macro to support nested iterable children access. [[@trivigy], #843]
      • Added bincode to the list of supported formats. [[@serzhiio], #806]
      • Added a noop() convenience method to Callback which creates a no-op callback. [[@mdtusz], #793]
      • The html! macro now accepts a Callback for element listeners. [[@jstarry], #777]
      struct MyComponent {
          onclick: Callback<ClickEvent>,
      }
    
      enum Msg {
          Click,
      }
    
      impl Component for MyComponent {
          type Message = Msg;
          type Properties = ();
    
          fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
              MyComponent {
                  onclick: link.callback(|_| Msg::Click),
              }
          }
    
          fn update(&mut self, msg: Self::Message) -> ShouldRender {
              match msg {
                  Msg::Click => true,
              }
          }
    
          fn view(&self) -> Html {
              html! {
                  <button onclick=&self.onclick>{ "Click me!" }</button>
              }
          }
      }
    
    • Add send_message_batch method to ComponentLink. [[@hgzimmerman], #748]
    • Allow compilation to wasi target without wasm_bindgen. [[@dunnock], #746]
    • AgentLink now implements Clone which enables Future usage without explicit Yew framework support. [[@izissise], #802]
    • ComponentLink now implements Clone which enables Future usage without explicit Yew framework support. [[@hgzimmerman], #749]
      use wasm_bindgen::JsValue;
      use wasm_bindgen_futures::future_to_promise;
    
      // future must implement `Future<Output = Component::Message> + 'static`
      let link = self.link.clone();
      let js_future = async move {
          link.send_message(future.await);
          Ok(JsValue::NULL)
      };
    
      future_to_promise(js_future);
    
    • ๐Ÿ›  #### ๐Ÿ›  Fixes

      • Fixed handling of boolean tag attributes. [[@mrh0057], #840]
      • Improved nested component ergonomics. [[@jstarry], #780]
      fn view(&self) -> Html {
          html! {
              <Wrapper>
                  // This is now valid. (before #780, this would cause a lifetime
                  // compile error because children nodes were moved into a closure)
                  <Nested on_click=&self.nested_on_click />
              </Wrapper>
          }
      }
    
    • Creating a Callback with ComponentLink is no longer restricted to mutable references, improving ergonomics. [[@jstarry], #780]
    • The Callback reform method no longer consumes self making it easier to "reverse map" a Callback. [[@jstarry], #779]
      pub struct ListHeader {
          props: Props,
      }
    
      #[derive(Properties, Clone)]
      pub struct Props {
          #[props(required)]
          pub on_hover: Callback<Hovered>,
          #[props(required)]
          pub text: String,
      }
    
      impl Component for ListHeader {
          type Message = ();
          type Properties = Props;
    
          fn create(props: Self::Properties, _: ComponentLink<Self>) -> Self {
              ListHeader { props }
          }
    
          fn update(&mut self, _: Self::Message) -> ShouldRender {
              false
          }
    
          fn view(&self) -> Html {
              let onmouseover = self.props.on_hover.reform(|_| Hovered::Header);
              html! {
                  <div class="list-header" onmouseover=onmouseover>
                      { &self.props.text }
                  </div>
              }
          }
      }
    
    • Reduced allocations in the Classes to_string method. [[@hgzimmerman], #772]
    • Empty string class names are now filtered out to prevent panics. [[@jstarry], #770]

      • #### ๐Ÿšจ Breaking changes
    • Components with generic args now need to be closed with the full type path. (e.g. html! { <Wrapper<String>></Wrapper<String>>}) [[@jstarry], #837]

    • Changed VTag listener type from Box<dyn Listener> to Rc<dyn Listener>. [[@jstarry], #786]

    • Properties need to implement Clone again in order to improve nested component ergonomics. [[@jstarry], #786]

    • Removed send_future method from ComponentLink since it is no longer necessary for using Futures with Yew. [[@hgzimmerman], #799]

    • Removed generic type parameter from Html and all virtual node types: VNode, VComp, VTag, VList, VText, etc. [[@jstarry], #783]

    • Removed support for macro magic closure syntax for element listeners. (See transition guide for how to pass a Callback explicitly instead). [[@jstarry], #782]

    • Renamed Agent methods and event type for clarity. handle -> handle_input, AgentUpdate -> AgentLifecycleEvent, response -> respond. [[@philip-peterson], #751]

    • The ComponentLink send_back method has been renamed to callback for clarity. [[@jstarry], #780]

    • The ComponentLink send_self and send_self_batch methods have been renamed to send_message and send_message_batch for clarity. [[@jstarry], #780]

    • The Agent send_back method has been renamed to callback for clarity. [[@jstarry], #780]

    • The VTag children value type has changed from Vec<VNode> to VList. [[@jstarry], #754]