Creating a dispatch
A Dispatch is the primary interface to access your Store. It can be used to read and write changes to state in various ways.
Hooks
A dispatch is provided when using the functional hook, which is only available in yew functional components.
IMPORTANT: Like other hooks, all yewdux hooks must be used at the top level of a function component.
#![allow(unused)] fn main() { extern crate yewdux; extern crate yew; use yewdux::prelude::*; use yew::prelude::*; #[derive(Default, PartialEq, Store)] struct State { count: u32, } #[function_component] fn MyComponent() -> Html { let (state, dispatch) = use_store::<State>(); html! { // Component stuff here } } }
See the docs for a full list of available hooks.
Manually
To create a dispatch, you need only provide the desired store type. This is available in any rust code, not just yew components.
#![allow(unused)] fn main() { extern crate yewdux; use yewdux::prelude::*; #[derive(Default, PartialEq, Store)] struct State { count: u32, } let dispatch = Dispatch::<State>::global(); }
NOTE: Here we create a global dispatch, which is only available for wasm targets. See SSR support for alternatives.
Changing state
Dispatch
provides many options for changing state. Here are a few handy methods. For a full list
see the docs
#![allow(unused)] fn main() { extern crate yewdux; extern crate yew; use yewdux::prelude::*; use yew::prelude::*; #[derive(Default, PartialEq, Store)] struct State { count: u32, } // Create a global dispatch let dispatch = Dispatch::<State>::global(); // Set the value immediately dispatch.set(State { count: 0 }); // Set the value immediately based on the last value dispatch.reduce(|state| State { count: state.count + 1}.into()); // Create a callback to set the value when a button is clicked let onclick = dispatch.reduce_callback(|state| State { count: state.count + 1}.into()); html! { <button {onclick}>{"Increment (+1)"}</button> }; }
Mut reducers
There are _mut
variants to every reducer function. This way has less boilerplate, and requires
your Store
to implement Clone
. Your Store
may be cloned once per mutation,
#![allow(unused)] fn main() { extern crate yewdux; extern crate yew; use yewdux::prelude::*; use yew::prelude::*; #[derive(Default, PartialEq, Clone, Store)] struct State { count: u32, } // Create a global dispatch let dispatch = Dispatch::<State>::global(); // Mutate the current value dispatch.reduce_mut(|state| state.count += 1); // Create a callback to mutate the value when a button is clicked let onclick = dispatch.reduce_mut_callback(|counter| counter.count += 1); html! { <button {onclick}>{"Increment (+1)"}</button> }; }
Predictable mutations
Yewdux supports predictable mutation. Simply define your message and apply it.
#![allow(unused)] fn main() { extern crate yewdux; extern crate yew; use std::rc::Rc; use yew::prelude::*; use yewdux::prelude::*; #[derive(Default, PartialEq, Clone, Store)] struct State { count: u32, } enum Msg { AddOne, } impl Reducer<State> for Msg { fn apply(self, state: Rc<State>) -> Rc<State> { match self { Msg::AddOne => State { count: state.count + 1 }.into(), } } } let dispatch = Dispatch::<State>::global(); dispatch.apply(Msg::AddOne); let onclick = dispatch.apply_callback(|_| Msg::AddOne); html! { <button {onclick}>{"Increment (+1)"}</button> }; }
Tip
Rc::make_mut
is handy if you prefer CoW:
#![allow(unused)] fn main() { extern crate yewdux; use std::rc::Rc; use yewdux::prelude::*; #[derive(Default, PartialEq, Clone, Store)] struct State { count: u32, } enum Msg { AddOne, } impl Reducer<State> for Msg { fn apply(self, mut state: Rc<State>) -> Rc<State> { let state_mut = Rc::make_mut(&mut state); match self { Msg::AddOne => state_mut.count += 1, }; state } } }
Future support
Because a Dispatch
may be created and executed from anywhere, Yewdux has innate future support.
Just use it normally, no additonal setup is needed.
#![allow(unused)] fn main() { extern crate yewdux; extern crate yew; use std::rc::Rc; use yewdux::prelude::*; use yew::prelude::*; #[derive(Default, PartialEq, Store)] struct User { name: Option<Rc<str>>, } async fn get_user() -> User { User { name: Some("bob".into()) } } let dispatch = Dispatch::<User>::global(); // Use yew::platform::spawn_local to run a future. let future = async move { let user = get_user().await; dispatch.set(user); }; }