rs-yew-crate

Yew Framework (v0.22)

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "rs-yew-crate" with this command: npx skills add padparadscho/skills/padparadscho-skills-rs-yew-crate

Yew Framework (v0.22)

Yew is a modern Rust framework for creating multi-threaded frontend web applications compiled to WebAssembly. It uses a virtual DOM, component-based architecture, and a JSX-like html! macro. MSRV: Rust 1.84.0.

Project Setup

Prerequisites

rustup target add wasm32-unknown-unknown cargo install --locked trunk

New Project (manual)

cargo new yew-app && cd yew-app

Cargo.toml:

[package] name = "yew-app" version = "0.1.0" edition = "2021"

[dependencies] yew = { version = "0.22", features = ["csr"] }

Feature csr enables Renderer and client-side rendering code. Omit for library crates. Use ssr for server-side rendering. Use serde for serde integration on AttrValue .

index.html (project root):

<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Yew App</title> </head> <body></body> </html>

src/main.rs:

use yew::prelude::*;

#[component] fn App() -> Html { let counter = use_state(|| 0); let onclick = { let counter = counter.clone(); move |_| { counter.set(*counter + 1); } };

html! {
    &#x3C;div>
        &#x3C;button {onclick}>{ "+1" }&#x3C;/button>
        &#x3C;p>{ *counter }&#x3C;/p>
    &#x3C;/div>
}

}

fn main() { yew::Renderer::<App>::new().render(); }

trunk serve --open

Starter Template

cargo generate --git https://github.com/yewstack/yew-trunk-minimal-template trunk serve

Trunk Configuration (Trunk.toml)

[serve] address = "127.0.0.1" port = 8080

Function Components

The recommended component model. Annotate with #[component] , name in PascalCase, return Html .

use yew::{component, html, Html};

#[component] fn HelloWorld() -> Html { html! { "Hello world" } }

// Usage: html! { <HelloWorld /> }

Properties (Props)

Derive Properties + PartialEq . Use AttrValue instead of String for attribute values (cheap to clone).

use yew::{component, html, Html, Properties};

#[derive(Properties, PartialEq)] pub struct Props { pub name: AttrValue, #[prop_or_default] pub is_loading: bool, #[prop_or(AttrValue::Static("default"))] pub label: AttrValue, #[prop_or_else(|| AttrValue::from("computed"))] pub dynamic: AttrValue, }

#[component] fn Greeting(&Props { ref name, is_loading, .. }: &Props) -> Html { if is_loading { return html! { "Loading" }; } html! { <p>{"Hello, "}{name}</p> } }

// Usage: html! { <Greeting name="Alice" is_loading=false /> }

Children: Use children: Html field name in props to receive nested content.

#[derive(Properties, PartialEq)] pub struct ContainerProps { pub children: Html, }

#[component] fn Container(props: &ContainerProps) -> Html { html! { <div class="wrapper">{ props.children.clone() }</div> } }

Auto-props (yew-autoprops crate): Generate Properties struct from function args.

use yew_autoprops::autoprops; // #[autoprops] must appear BEFORE #[component] #[autoprops] #[component] fn Greetings(#[prop_or_default] is_loading: bool, message: &AttrValue) -> Html { html! { <>{message}</> } }

Callbacks

Callback<IN, OUT> wraps Fn in Rc . Use Callback::from(|e| ...) for event handlers. Pass down as props for child-to-parent communication.

// Passing callbacks as props #[derive(Properties, PartialEq)] pub struct ButtonProps { pub on_click: Callback<Video>, }

// Creating callbacks with state let selected = use_state(|| None); let on_select = { let selected = selected.clone(); Callback::from(move |video: Video| selected.set(Some(video))) };

Hooks

Rules: (1) name starts with use_ , (2) call only at top-level of component/hook, (3) same call order every render.

Pre-defined hooks:

  • use_state / use_state_eq — reactive local state

  • use_reducer / use_reducer_eq — complex state via reducer pattern

  • use_effect / use_effect_with — side effects (not run during SSR)

  • use_memo — memoized computation

  • use_callback — memoized callback

  • use_context — consume context value

  • use_ref / use_mut_ref — persistent mutable reference

  • use_node_ref — DOM node reference

  • use_force_update — manual re-render trigger

// State let counter = use_state(|| 0); counter.set(*counter + 1);

// Effect with deps (runs when deps change) { let data = data.clone(); use_effect_with(deps, move |_| { // setup logic || () // cleanup }); }

// Reducer use yew::prelude::*;

enum Action { Increment, Decrement } struct State { count: i32 }

impl Reducible for State { type Action = Action; fn reduce(self: Rc<Self>, action: Action) -> Rc<Self> { match action { Action::Increment => Self { count: self.count + 1 }.into(), Action::Decrement => Self { count: self.count - 1 }.into(), } } }

let state = use_reducer(|| State { count: 0 }); state.dispatch(Action::Increment);

Custom hooks: Annotate with #[hook] , compose from built-in hooks.

use yew::prelude::*;

#[hook] pub fn use_toggle(initial: bool) -> (bool, Callback<()>) { let state = use_state(move || initial); let toggle = { let state = state.clone(); Callback::from(move |_| state.set(!*state)) }; (*state, toggle) }

html! Macro

For detailed syntax rules, element attributes, conditional rendering, fragments, and lists, see references/html_and_events.md.

Key rules:

  • Single root node required (use <>...</> fragments for multiple)

  • String literals must be quoted and wrapped in braces: { "text" }

  • Tags must self-close (<br /> ) or have matching close tags

  • Rust expressions go in { ... }

  • if / if let for conditional rendering

  • for item in iter { ... } for lists (add key prop)

html! { <> <h1>{ "Title" }</h1> if show_subtitle { <p>{ "Subtitle" }</p> } for item in &items { <li key={item.id}>{ &item.name }</li> } </> }

Routing

Add yew-router crate. See references/routing.md for nested routers, basename, and query parameters.

use yew::prelude::; use yew_router::prelude::;

#[derive(Clone, Routable, PartialEq)] enum Route { #[at("/")] Home, #[at("/post/:id")] Post { id: String }, #[not_found] #[at("/404")] NotFound, }

fn switch(route: Route) -> Html { match route { Route::Home => html! { <h1>{"Home"}</h1> }, Route::Post { id } => html! { <p>{format!("Post {}", id)}</p> }, Route::NotFound => html! { <h1>{"404"}</h1> }, } }

#[component] fn App() -> Html { html! { <BrowserRouter> <Switch<Route> render={switch} /> </BrowserRouter> } }

Navigation: <Link<Route> to={Route::Home}>{"Home"}</Link<Route>> or use_navigator() hook.

Contexts

Provide shared state without prop drilling. See references/contexts_and_state.md.

#[derive(Clone, PartialEq)] struct Theme { foreground: String, background: String }

// Provider #[component] fn App() -> Html { let theme = Theme { foreground: "#000".into(), background: "#fff".into() }; html! { <ContextProvider<Theme> context={theme}> <ThemedButton /> </ContextProvider<Theme>> } }

// Consumer #[component] fn ThemedButton() -> Html { let theme = use_context::<Theme>().expect("no theme context"); html! { <button style={format!("color: {}", theme.foreground)}>{"Click"}</button> } }

Data Fetching

Use gloo-net for HTTP, serde for deserialization, wasm-bindgen-futures for async.

[dependencies] yew = { version = "0.22", features = ["csr", "serde"] } gloo-net = "0.6" serde = { version = "1.0", features = ["derive"] } wasm-bindgen-futures = "0.4"

use gloo_net::http::Request; use yew::prelude::*;

#[component] fn App() -> Html { let data = use_state(Vec::new); { let data = data.clone(); use_effect_with((), move |_| { let data = data.clone(); wasm_bindgen_futures::spawn_local(async move { let resp: Vec<Item> = Request::get("/api/items") .send().await.unwrap() .json().await.unwrap(); data.set(resp); }); || () }); } // render data... html! {} }

Events and DOM Interaction

See references/html_and_events.md for full event type table and typed event targets.

// Input handling with TargetCast use web_sys::HtmlInputElement; use yew::prelude::*;

#[component] fn TextInput() -> Html { let value = use_state(String::default); let oninput = { let value = value.clone(); Callback::from(move |e: InputEvent| { let input: HtmlInputElement = e.target_unchecked_into(); value.set(input.value()); }) }; html! { <input type="text" {oninput} value={(*value).clone()} /> } }

Server-Side Rendering

See references/ssr.md for SSR setup, hydration, Suspense integration, and component lifecycle during SSR.

Agents (Web Workers)

Offload tasks to web workers for concurrent processing. Use yew-agent crate. Agents support Public (singleton) and Private (per-bridge) modes. Communication via bridges (bidirectional) and dispatchers (unidirectional). Messages serialized with bincode .

Anti-Patterns to Avoid

  • String in props — Use AttrValue (cheap clone via Rc<str> )

  • Vec<T> in props — Use IArray<T> from implicit-clone

  • Interior mutability (RefCell , Mutex ) — Yew can't detect changes; use hooks

  • Side effects in render — Move to use_effect / use_effect_with

  • Missing keys on lists — Always add key to iterated elements

  • Accessing Web APIs during SSR — Isolate in use_effect (not run server-side)

Ecosystem & Common Dependencies

Crate Purpose

yew-router

Client-side routing

gloo

Ergonomic web APIs (net, timers, storage, events, dialogs)

gloo-net

HTTP requests (fetch)

wasm-bindgen

Rust ↔ JS interop

wasm-bindgen-futures

Async/await in WASM

web-sys

Raw Web API bindings

js-sys

JavaScript standard built-in bindings

serde / serde_json

Serialization

stylist

CSS-in-Rust

yewdux

Redux-like state management

yew-hooks

Community hooks collection

yew-autoprops

Auto-generate props structs

bounce

State management (Redux/Recoil-inspired)

implicit-clone

Cheap-clone types (IString , IArray )

References

  • HTML macro, events, and DOM interaction: references/html_and_events.md

  • Routing (yew-router) patterns: references/routing.md

  • Contexts and state management: references/contexts_and_state.md

  • Server-side rendering and hydration: references/ssr.md

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

rs-ratatui-crate

No summary provided by upstream source.

Repository SourceNeeds Review
General

js-gnome-extensions

No summary provided by upstream source.

Repository SourceNeeds Review
General

js-gnome-apps

No summary provided by upstream source.

Repository SourceNeeds Review
General

js-stellar-sdk

No summary provided by upstream source.

Repository SourceNeeds Review