--- title: "use_reducer" --- `use_reducer` is an alternative to [`use_state`](./use-state). It is used to handle more complex component's state. It accepts an initial state function and returns a `UseReducerHandle` that dereferences to the state, and a dispatch function. The dispatch function takes one argument of type `Action`. When called, the action and current value are passed to the reducer function which computes a new state that is returned, and the component is re-rendered. :::tip Advanced tip The dispatch function is guaranteed to be the same across the entire component lifecycle. You can safely omit the `UseReducerHandle` from the dependents of `use_effect_with_deps` if you only intend to dispatch values from within the hooks. ::: The state object returned by the initial state function is required to implement a `Reducible` trait which provides an `Action` type and a reducer function. This hook will always trigger a re-render upon receiving an action. See [`use_reducer_eq`](#use_reducer_eq) if you want the component to only re-render when the state changes. ## Example ```rust use yew::prelude::*; use std::rc::Rc; /// reducer's Action enum CounterAction { Double, Square, } /// reducer's State struct CounterState { counter: i32, } impl Default for CounterState { fn default() -> Self { Self { counter: 1 } } } impl Reducible for CounterState { /// Reducer Action Type type Action = CounterAction; /// Reducer Function fn reduce(self: Rc, action: Self::Action) -> Rc { let next_ctr = match action { CounterAction::Double => self.counter * 2, CounterAction::Square => self.counter.pow(2) }; Self { counter: next_ctr }.into() } } #[function_component] fn ReducerExample() -> Html { // The use_reducer hook takes an initialization function which will be called only once. let counter = use_reducer(CounterState::default); let double_onclick = { let counter = counter.clone(); Callback::from(move |_| counter.dispatch(CounterAction::Double)) }; let square_onclick = { let counter = counter.clone(); Callback::from(move |_| counter.dispatch(CounterAction::Square)) }; html! { <>
{ counter.counter }
} } ``` :::caution The value held in the handle will reflect the value of at the time the handle is returned by the `use_reducer`. It is possible that the handle does not dereference to an up to date value if you are moving it into a `use_effect_with_deps` hook. You can register the state to the dependents so the hook can be updated when the value changes. ::: ## `use_reducer_eq` This hook has the same effect as `use_reducer` but will only trigger a re-render when the reducer function produces a value that `prev_state != next_state`. This hook requires the state object to implement `PartialEq` in addition to the `Reducible` trait required by `use_reducer`.