# 簡述 useReducer
語法:`const [state, dispatch] = useReducer(reducer, initialArg, init);`
- `useReducer` 第一個參數用來設定變更 state 的規則,特定的 action 時如何更新 state
- `useReducer` 第二個參數是初始化的 state
- `useReducer` 第三個參數是初始化 state 的函式,非必要的參數,用來抽出`initialArgs` 的計算邏輯
- dispatch 用來觸發 action
```jsx=
import React, { useReducer } from "react";
// 初始化 state
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case "increment":
return { count: state.count + 1 };
case "decrement":
return { count: state.count - 1 };
case "reset":
return { count: (state.count = 0) };
default:
return { count: state.count };
}
}
export default function App() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
Count: {state.count}
<br />
<br />
<button onClick={() => dispatch({ type: "increment" })}>Increment</button>
<button onClick={() => dispatch({ type: "decrement" })}>Decrement</button>
<button onClick={() => dispatch({ type: "reset" })}>Reset</button>
</div>
);
}
```
[example code](https://codesandbox.io/s/crimson-browser-xm3nh)
## 第三個參數
As far as I can experiment, the `init` function as third arg is a transformer of the `initialState`.
It means that `initialState` will not be used a initial state, but as argument for `init` function. The return of this one will be the true `initialState`. It could be useful to avoid huge parameter during the `useReducer` initialization line.
- code
```jsx=
function init(initialCount) {
return {count: initialCount};
}
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
case 'reset':
return init(action.payload);
default:
throw new Error();
}
}
function Counter({initialCount}) {
const [state, dispatch] = useReducer(reducer, initialCount, init);
return (
<>
Count: {state.count}
<button
onClick={() => dispatch({type: 'reset', payload: initialCount})}>
Reset
</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
```
# 參考資料
[Day6-React Hook 篇-useReducer - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天](https://ithelp.ithome.com.tw/articles/10268258?sc=hot)
[What's the purpose of the 3rd argument in useReducer?](https://stackoverflow.com/questions/59041341/whats-the-purpose-of-the-3rd-argument-in-usereducer)