yew-callbacks

Crates.ioyew-callbacks
lib.rsyew-callbacks
version0.2.1
sourcesrc
created_at2023-01-13 13:43:47.769954
updated_at2023-01-17 12:28:02.326834
descriptionCreate and manage callbacks per component without creating duplicates
homepagehttps://github.com/cecton/yew-callbacks
repositoryhttps://github.com/cecton/yew-callbacks
max_upload_size
id757927
size77,022
Cecile Tonglet (cecton)

documentation

https://docs.rs/yew-callbacks

README

Rust Latest Version Rust 1.60+ License Docs.rs LOC Dependency Status

yew-callbacks

Yet another crate nobody asked for.

This crate provides a derive macro Callbacks that can be used on Yew enum messages to help managing callbacks.

But why

Callbacks in Yew's components are easy to create but hard to manage. To avoid duplication you should create them preemptively in the create() method of your component, store them in the state of your component, then pass clones to the children. Unfortunately this creates a lot of bloat.

To address this, yew-callbacks provides a macro that will automatically create some kind of cache for your callbacks. You create this cache once in the create() method of your component and then you can use the methods to get your callbacks easily.

Example

use yew::prelude::*;
use yew_callbacks::Callbacks;

#[derive(Debug, Callbacks)]
enum Msg {
    OnClick(MouseEvent),
}

#[derive(Debug)]
struct App {
    cb: MsgCallbacks<Self>,
}

impl Component for App {
    type Message = Msg;
    type Properties = ();

    fn create(ctx: &Context<Self>) -> Self {
        Self {
            cb: ctx.link().into(),
        }
    }

    fn view(&self, ctx: &Context<Self>) -> Html {
        html! {
            <button onclick={self.cb.on_click()}>
                { "Hello World!" }
            </button>
        }
    }
}

Why care

Not perf.

Your children components will be updated if their properties changed. If you do onclick={ctx.link().callback(Msg::OnClick) then the child component will think there is an update every time the parent component updates. This is because doing ctx.link().callback(Msg::OnClick) creates a new callback every time.

Handling multiple child components

This crate also allows currying the arguments of your callback.

Example

use yew::prelude::*;
use yew_callbacks::Callbacks;

#[derive(Debug, Callbacks)]
enum Msg {
    OnClick(#[curry] usize, MouseEvent),
}

#[derive(Debug)]
struct App {
    games: Vec<AttrValue>,
    cb: MsgCallbacks<Self>,
}

impl Component for App {
    type Message = Msg;
    type Properties = ();

    fn create(ctx: &Context<Self>) -> Self {
        Self {
            games: vec![
                "Freedom Planet 2".into(),
                "Asterigos: Curse of the Stars".into(),
                "Fran Bow".into(),
                "Cats in Time".into(),
                "Ittle Dew 2+".into(),
                "Inscryption".into(),
            ],
            cb: ctx.link().into(),
        }
    }

    fn view(&self, _ctx: &Context<Self>) -> Html {
        self
            .games
            .iter()
            .enumerate()
            .map(|(i, game)| html! {
                <button onclick={self.cb.on_click(i)}>
                    { format!("You should try {game}") }
                </button>
            })
            .collect()
    }
}
Commit count: 4

cargo fmt