# how to useReducer

## 1. Definition

**useReducer** is usually preferable to useState when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one.

It accepts a reducer of type **(state, action) => newState**, and returns the **current state** paired with a dispatch method. (If you’re familiar with Redux, you already know how this works.

Here is the countReducer example;

```jsx
const initialState = { count: 0 }

const counterReducer = (state, action) => {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}
```

## 2. Specifying the initial State

There are two ways to initialized the useReducer state;

### 2.1. Basic

We can just give it as a second argument to useReducer call;

```jsx
const [state, dispatch] = useReducer(
  countReducer,
  { count: 0 } // second argument
);
```

### 2.2. Lazy Initialization

We can also initialize it lazily by giving it as a third parameter as a function;

```jsx
const initState = (defaultCount) => ({ count: defaultCount })

const Counter = ({ counter }) => {
	const [state, dispatch] = useReducer(
	  countReducer,
	  counter, // second argument
		initState // third argument
	);
	
	// Rest of the component...
}
```

## 3. Usage

After we initialize it we just need to call dispatch functions that we are getting from useReducer hook and use it as a handler inside our elements.

>React guarantees that dispatch function identity is stable and won’t change on re-renders. 

```jsx
const Counter = ({ counter }) => {
	const [state, dispatch] = useReducer(countReducer, 0);
	
	return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}
```

## 4. Links
- [React useReducer docs](https://reactjs.org/docs/hooks-reference.html#usereducer)
