---
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<Self>, action: Self::Action) -> Rc<Self> {
        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! {
        <>
            <div id="result">{ counter.counter }</div>

            <button onclick={double_onclick}>{ "Double" }</button>
            <button onclick={square_onclick}>{ "Square" }</button>
        </>
    }
}
```

:::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`.
