Yew Tutorial (v0.19) - part 1

Page content

Before Yew tutorial

I want to try with wasm-pack, but after several tries, I realized that it was a bad try. And most parts of the official document uses Trunk, so I was back to Trunk.

Please refer to my post about Trunk.

Versions

  • Cargo: 1.65
  • Yew: 0.19

Set up Rust environment for Yew

rustup target add wasm32-unknown-unknown
cargo install trunk

My summary on Yew tutorial page

I followed the official “Video page” tutorial.

Basic ideas

  • Yew injects body element by default. You can change which part to be injected.
  • In Yew world, you will create a lot of components. They are literally components of an app in Yew world.
  • You can create component by adding an attribute to function, like #[function_component(NameComponent)].
  • Or, impl Component for NameComponent. Function components are recommended by official, but we will see this impl way in the next part).
  • You can launch your app (the entry component) by yew::start_app::<NameComponent>();.
  • html! macro enable to write JSX-like syntax.
    • Expressions must be wrapped in curly braces ({ }).
    • There must only be one root node. If you want to have multiple elements without wrapping them in a container, an empty tag/fragment (<> ... </>) is used.
  • In Yew world, there are two types of components. function component, and struct component.
    • Actually, yew::start_app::<NameComponent>(); run the function component NameComponent.
  • You can define struct component by adding attribute #[derive(Properties)] to struct. Struct components are data, used by input of function components.
  • A function component takes only one property argument.
  • If function returns Html type, for example, you can use a function component like this:
    // in html! macro
    <MyPropStruct field1={my_struct.clone()} />
    
  • Properties are used to pass data down from a parent component to a child component. Changin property could make your Yew app interactive (non-static).

Change HTML page

  • Page actions can be defined by Callback enum.
  • There are only two components in Yew world, so every action is kicked by Components.
  • For example, to change the view, struct component need to notify its “parent” component the change (passing handlers).
  • Callback functions could be used with the onclick attribute:
    html! {
        <p onclick={my_callback}>
            {format!("{}: {}", video.speaker, video.title)}
        </p>
    }
    

Hook

Hooks are functions that let you “hook into” components’ state and/or lifecycle and perform actions.

use_state

How to use callback

  1. Include a callback function in a Struct property (the type is Callback<T>).

    #[derive(Properties, PartialEq)]
    struct VideosListProps {
        videos: Vec<Video>,
        on_click: Callback<Video>
    }
    
  2. Create a (callback) function component which takes the struct property as a parameter.

    #[function_component(VideosList)]
    fn videos_list(VideosListProps { videos, on_click }: &VideosListProps) -> Html
    
  3. Set the callback function. In the function component, emit method calls the callback function. (More precisely, emit method send a Message enum to the component.)

    let on_video_select = {
        let on_click = on_click.clone();
        let video = video.clone();
        Callback::from(move |_| {
            on_click.emit(video.clone())
        })
    };
    
  4. You can set the callback function in HTML by onclick={callback_function}

    html! {
        <p onclick={on_video_select}>{format!("{}: {}", video.speaker, video.title)}</p>
    }
    
  5. Use the callback in other components:

    // Set a hook
    let selected_video = use_state(|| None);
    
    // Set a callback function
    let on_video_select = {
        let selected_video = selected_video.clone();
        Callback::from(move |video: Video| {
            selected_video.set(Some(video))
        })
    };
    // --snip--
    html! {
        <>
            <h1>{ "RustConf Explorer" }</h1>
            <div>
                <h3>{"Videos to watch"}</h3>
                <VideosList videos={(*videos).clone()} on_click={on_video_select.clone()} />
            </div>
            { for details }
        </>
    }
    

Other take-aways

Fetch external resource from WASM

use reqwasm::http::Request;

Avoid CORS error during local development

trunk serve --proxy-backend=https://yew.rs/tutorial

Terminologies

The terminologies in Yew are quite similar to that of React.

Here is a quote from official README.

Developers who have experience using JSX in React should feel quite at home when using Yew.

For example, the concept of states, components, props are totally similar to React’s.