Reading state

To get the current state of your store immediately, use Dispatch::get:

IMPORTANT: Reading the state this way does not provide any sort of change detection, and your component will not automatically re-render when state changes.


#![allow(unused)]
fn main() {
extern crate yewdux;
use std::rc::Rc;

use yewdux::prelude::*;

#[derive(PartialEq, Default, Store)]
struct State {
    count: u32,
}

// Create a dispatch from the global context. This works for non-global contexts too, we would just
// pass in the context we want.
let dispatch = Dispatch::<State>::global();
let state: Rc<State> = dispatch.get();
}

Subscribing to your store

In order for your component to know when state changes, we need to subscribe.

Function components

The use_store hook automatically subscribes to your store, and re-renders when state changes. This must be called at the top level of your function component.


#![allow(unused)]
fn main() {
extern crate yewdux;
extern crate yew;
use yewdux::prelude::*;
use yew::prelude::*;
#[derive(PartialEq, Default, Store)]
struct State {
    count: u32,
}
#[function_component]
fn ViewCount() -> Html {
    let (state, dispatch) = use_store::<State>();
    html!(state.count)
}
}

Struct components

For struct components we need to subscribe manually. This way allows much finer control, at the cost of extra boilerplate.

IMPORTANT: Remember to hold onto your dispatch instance. Dropping it will drop the entire subscription, and you will not receive changes to state.


#![allow(unused)]
fn main() {
extern crate yewdux;
extern crate yew;
use std::rc::Rc;

use yew::prelude::*;
use yewdux::prelude::*;

#[derive(PartialEq, Default, Clone, Store)]
struct State {
    count: u32,
}

struct MyComponent {
    dispatch: Dispatch<State>,
    state: Rc<State>,

}

enum Msg {
    StateChanged(Rc<State>),
}

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

    fn create(ctx: &Context<Self>) -> Self {
        // The callback for receiving updates to state.
        let callback = ctx.link().callback(Msg::StateChanged);
        // Subscribe to changes in state. New state is received in `update`. Be sure to save this,
        // dropping it will unsubscribe.
        let dispatch = Dispatch::<State>::global().subscribe_silent(callback);
        Self {
            // Get the current state.
            state: dispatch.get(),
            dispatch,
        }
    }

    fn update(&mut self, ctx: &Context<Self>, msg: Msg) -> bool {
        match msg {
            // Receive new state.
            Msg::StateChanged(state) => {
                self.state = state;

                // Only re-render this component if count is greater that 0 (for this example).
                if self.state.count > 0 {
                    true
                } else {
                    false
                }
            }
        }
    }

    fn view(&self, ctx: &Context<Self>) -> Html {
        let count = self.state.count;
        let onclick = self.dispatch.reduce_mut_callback(|s| s.count += 1);
        html! {
            <>
            <h1>{ count }</h1>
            <button onclick={onclick}>{"+1"}</button>
            </>
        }
    }

}
}

Selectors

Sometimes a component will only care about a particular part of state, and only needs to re-render when that part changes. For this we have the use_selector hook.


#![allow(unused)]
fn main() {
extern crate yewdux;
extern crate yew;
use yewdux::prelude::*;
use yew::prelude::*;

#[derive(Default, Clone, PartialEq, Store)]
struct User {
    first_name: String,
    last_name: String,
}

#[function_component]
fn DisplayFirst() -> Html {
    // This will only re-render when the first name has changed. It will **not** re-render if any
    // other field has changed.
    //
    // Note: we are cloning a string. Probably insignificant for this example, however
    // sometimes it may be beneficial to wrap fields that are expensive to clone in an `Rc`.
    let first_name = use_selector(|state: &User| state.first_name.clone());

    html! {
        <p>{ first_name }</p>
    }
}
}

Capturing your environment

For selectors that need to capture variables from their environment, be sure to provide them as dependencies to use_selector_with_deps. Otherwise your selector won't update correctly!


#![allow(unused)]
fn main() {
extern crate yewdux;
extern crate yew;
use std::collections::HashMap;

use yewdux::prelude::*;
use yew::prelude::*;

#[derive(Default, Clone, PartialEq, Store)]
struct Items {
    inner: HashMap<u32, String>,
}

#[derive(Clone, PartialEq, Properties)]
struct DisplayItemProps {
    item_id: u32,
}

#[function_component]
fn DisplayItem(props: &DisplayItemProps) -> Html {
    // For multiple dependencies, try using a tuple: (dep1, dep2, ..)
    let item = use_selector_with_deps(
        |state: &Items, item_id| state.inner.get(item_id).cloned(),
        props.item_id,
    );
    // Only render the item if it exists.
    let item = match item.as_ref() {
        Some(item) => item,
        None => return Default::default(),
    };

    html! {
        <p>{ item }</p>
    }
}
}