A lightning fast state management module for Yew.

Related tags

Utilities state store yew
Overview

yewv Rust

A lightning fast state management module for Yew built with performance and simplicity as a first priority.

Who is this for?

If you wish to use a store alongside Yew fonction components, this library is made for you.

Install

Add the following dependency to your Cargo.toml.

[dependencies]
yewv = "0.2"

Usage

The following need to be respected while using this library:

  1. Only works with Yew function components.
  2. Store and service contexts must be registered in a parent or root component with ContextProvider.
  3. Store and service need to be used in a child component with use_store/use_service.
  4. As opposed to map_ref|watch_ref, map|watch are hooks and should not be called inside loops, conditions or callbacks.

Simple app with store

// main.rs
use yew::prelude::*;
use yewv::*;

struct AppState {
    count: i32,
}

#[function_component(App)]
fn app() -> Html {
    let store = StoreContext::new(AppState { count: 0 });
    html! {
        <ContextProvider<StoreContext<AppState>> context={store}>
            <Counter />
            <Counter />
        </ContextProvider<StoreContext<AppState>>>
    }
}

#[function_component(Counter)]
fn counter() -> Html {
    let store = use_store::<AppState>();
    let count = store.map_ref(|state| &state.count);
    let onclick = {
        let store = store.clone();
        move |_| {
            let state = store.state();
            store.set_state(AppState {
                count: state.count + 1,
            });
        }
    };
    html! {
        <button {onclick}>{format!("{} +", count)}</button>
    }
}

fn main() {
    yew::start_app::<App>();
}

Simple app with store and service

// main.rs
use yew::prelude::*;
use yewv::*;

struct AppState {
    count: i32,
}

struct AppService {
    store: StoreContext<AppState>,
}

impl AppService {
    fn increment_count(&self) {
        let state = self.store.state();
        self.store.set_state(AppState {
            count: state.count + 1,
        });
    }
}

#[function_component(App)]
fn app() -> Html {
    let store = StoreContext::new(AppState { count: 0 });
    let service = ServiceContext::new(AppService {
        store: store.clone(),
    });
    html! {
        <ContextProvider<StoreContext<AppState>> context={store}>
        <ContextProvider<ServiceContext<AppService>> context={service}>
            <Counter />
            <Counter />
        </ContextProvider<ServiceContext<AppService>>>
        </ContextProvider<StoreContext<AppState>>>
    }
}

#[function_component(Counter)]
fn counter() -> Html {
    let service = use_service::<AppService>();
    let store = use_store::<AppState>();

    let count = store.map_ref(|state| &state.count);
    let onclick = move |_| service.increment_count();

    html! {
        <button {onclick}>{format!("{} +", count)}</button>
    }
}

fn main() {
    yew::start_app::<App>();
}

map vs map_ref & watch vs watch_ref

If you only wish to reference a value owned by the store, you should use map_ref or watch_ref. As opposed to map|watch, map_ref|watch_ref don't take ownership of the referenced value. It is usually preferable to use map_ref|watch_ref over map|watch when possible. However, it is not always possible to use map_ref|watch_ref. For instance, if the value you wish to access is not owned by the store state, you will need to use map|watch:

let length = store.map(|state| state.some_vector.len());

Why is it so fast?

Custom hooks

The store utilizes highly optimized custom hooks for better performance and memory efficiency.

Renders only when and where needed

Subscriptions done to the store with map, map_ref, watch and watch_ref will only trigger a re-render if the observed value has changed.

Reference VS Ownership

Instead of propagating clone/copy of the application state throughout components, references are used.

Good practices

Reference only what's needed

When you are observing a value in a store, make sure you are not taking more than necessary. For instance, if you are only interested in a single value from a vector, there is no need to reference the entire vector:

let first = store.map_ref(|state| &state.some_vector[0]);
let last = store.map_ref(|state| state.some_vector.iter().last().expect("to have a value"));

Segregation of stores in large applications

When and where it makes sense, try to break your monolithic stores into multiple. Doing so will improve the performance of the application as a whole.

Credits

You might also like...
A module for masscan

A module for masscan

Example of executing ES module exports from Rust

rusty_esm This is an example showcasing a common use case for embedding Deno - calling JS module exports from Rust. The rest is pretty self explainato

💫 Small microservice to handle state changes of Kubernetes pods and post them to Instatus or Statuspages

💫 Kanata Small microservice to handle state changes of Kubernetes pods and post to Instatus 🤔 Why? I don't really want to implement and repeat code

Automatically build a Rust module tree from the project directory structure

Hypermod An even lazier version of automod and supermod. Searches the src/ directory recursively for .rs files, then builds a module tree using the di

Director is a simple, versatile, ergonomic state machine in Rust-lang.

Director Director is a simple, versatile, ergonomic state machine in Rust-lang. (no-std) | Examples | Docs | Latest Note | director = "0.5.0" Why? Bec

Component-based state machine plugin for Bevy

seldom_state is a component-based state machine plugin for Bevy. It's useful for AI, player state, and other entities that occupy various states. It allows for greater reusability of state logic between entities, compared to managing mutually-exclusive components directly in your systems.

A Polkadot SDK-like state machine written from scratch in Rust.

Rust State Machine This repository is the basis for a tutorial teaching how to develop a simple state machine using Rust. Goal The goal of this tutori

Pure rust implementation of python's random module with compatible generator behaviour.

pyrand Pure rust implementation of (parts of) python's random module with compatible PRNG behaviour: seeding with equivalent values will yield identic

An opinionated, practical color management library for games and graphics.

colstodian An opinionated color management library built on top of kolor. Introduction colstodian is a practical color management library for games an

Releases(v0.2.3)
Owner
null
A Rust library that implements the main lightning logic of the lipa wallet app.

lipa-lightning-lib (3L) Warning This library is not production ready yet. Build Test Start Nigiri Bitcoin: nigiri start --ln The --ln flag is not stri

lipa 9 Dec 15, 2022
A fork of yew-router

Yew Router (fork) This is fork of version 0.15 of the yew-router. Motivation The main motivation behind the fork is the lack of nested router support

Jens Reimann 2 Jan 4, 2022
This is a small demo to accompany the Tauri + Yew tutorial

Tauri + Yew Demo This is a small demo to accompany the Tauri + Yew tutorial

Steve Pryde 94 Jan 2, 2023
Rust + Yew + Axum + Tauri, full-stack Rust development for Desktop apps.

rust-yew-axum-tauri-desktop template Rust + Yew + Axum + Tauri, full-stack Rust development for Desktop apps. Crates frontend: Yew frontend app for de

Jet Li 54 Dec 23, 2022
A framework experience for Yew.

stackable A framework experience for Yew. Stackable provides a development stack with: Tooling around Server-side Rendering Support. An easy-to-use, S

Kaede Hoshikawa 8 Dec 30, 2022
Styling framework for Yew ✂

??‍♂️ + ?? -> Hallings - components for Yew ❓ Purpose What if there existed a couple of pre-built components for yew like password strength checker or

David Styrbjörn 3 Jan 6, 2023
SimpleX Chat GUI built with Rust, Tauri and Yew

simplex-desktop A desktop application for simplex-chat. WIP, contributions are welcome. Architecture For the back end we rust with tauri and frontend

Simon Shine 5 Feb 28, 2023
Scaffold that provides a basic setup for a Yew app with DaisyUI for styling.

Yew and Tailwind CSS Scaffold This scaffold provides a basic setup for a Yew app with Tailwind CSS for styling. It also includes DaisyUI, a Tailwind C

Alessio Marchi 6 Mar 3, 2023
Awesome full-stack template using Yew and Rust

Docker + Actix + Yew Full Stack Template ??‍?? YouTube videos Full Stack Rust App Template using Yew + Actix! https://youtu.be/oCiGjrpGk4A Add Docker

Security Union 143 Jun 22, 2023
Rust experiments involving Haskell-esque do notation, state, failure and Nom parsers!

Introduction As a long time Haskell developer recently delving into Rust, something I've really missed is monads and do notation. One thing monadic do

Kerfuffle 23 Feb 28, 2022