【React】UseReducerの使い方

## useReducerとは？？
***useReducer***は、useStateと同じく値を管理できるフック
***useReducer***:更新を***状態側***で行う
***useState***:更新は***利用者側***で行う

## useStateの場合
ここではボタンを押すとカウントアップするプログラムを作成した
```typescript
import { useState } from "react";

const Example = () => {
  const [state, setState] = useState(0);

  const countUp = () => {
    //useStateを使う場合は呼び出し時(使うとき)に処理を記述する
    setState((prev) => prev + 1);
  };

  return (
    <>
      <h3>{state}</h3>
      <button onClick={countUp}>カウントアップ</button>
    </>
  );
};
export default Example;
```

カウントアップボタンをクリックすると`countUp`関数が呼ばれる
その中で`setState`が使用され、`useState`の場合、呼び出し時に` setState((prev) => prev + 1);`という処理を記述して、カウントアップをしている

## useReducerの場合
* useReducerの書き方
```typescript
const [state, dispatch] = useReducer(reducer, initialState);
```
***reducer***:stateを更新するための関数。stateとactionを受け取って新しいstateを返す。
***initialState***:stateの初期値

initialStateは`useState()`の()の中身の値(初期値)の宣言と同じ

```typescript
import { useReducer } from "react";
const Example = () => {
    //useReducerを使う場合は定義の時点でstateをどのように更新するか、処理内容を書く
    const [state, dispatch] = useReducer(prev => prev + 1, 0);
    const rcountUp = () => {
        dispatch();
    };

    return (
        <>
          <h3>{state}</h3>
          <button onClick={rcountUp}>カウントアップ</button>
        </>
    );
};
```

カウントアップボタンをクリックすると`rcountUp`関数が呼ばれる
`useReducer`内で`prev => prev + 1`という処理が記述されているため、`dispatch`を呼ぶときは処理を記述しなくても良い。

## useReducerで条件分岐を行う
カウントアップとカウントダウンを実装する
```typescript
import { useReducer } from "react";
const Example = () => {
  const [state, dispatch] = useReducer((prev, {type}) => {
      if(type === '+'){
        return ++prev;
      }else if(type === '-'){
        return --prev;
      }
  }, 0);

  const rcountUp = () => {
    dispatch({ type: "+"});
  };

  const rcountDown = () => {
    dispatch({ type: "-"});
  };

  return (
    <>
      <h3>{state}</h3>
      <button onClick={rcountUp}>カウントアップ</button>
      <button onClick={rcountDown}>カウントダウン</button>
    </>
  );
};

export default Example;
```
選択されるボタンによって`{type:'+'}`または`{type:'-'}`が引数として渡される。
引き数をif文で分岐させ、`+`であればカウントアップ、`-`であればカウントダウンを行う。

## useReducerで引数を二つ渡す
```typescript
import { useReducer } from "react";
const Example = () => {
  const [state, dispatch] = useReducer((prev, { type, step }) => {
      switch (type) {
      case "+":
        return prev + step;
      case "-":
        return prev - step;
      default:
        throw new Error("実行できませんでした");
  }, 0);

  const rcountUp = () => {
    dispatch({ type: "+", step: 2 });
  };

  const rcountDown = () => {
    dispatch({ type: "-", step: 1 });
  };

  return (
    <>
      <h3>{state}</h3>
      <button onClick={rcountUp}>カウントアップ</button>
      <button onClick={rcountDown}>カウントダウン</button>
    </>
  );
};

export default Example;
```
引き数を2つ渡すには、上記と同様にカウントアップであれば`{type:'+', step:'2'}`とする。カウントアップをする際に+2をするため、stepに2を渡している。カウントダウンであれば`{type:'-', step:'1'}`となる。
useReducer内の処理で`+`,`-`で分岐し、渡された`step`で加算、減算を行っている。

カウントアップをクリックした後↓
![スクリーンショット 2022-10-27 120457.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884542/3a1c3f9b-fec8-dfb7-ae04-435b5581263c.png)

カウントアップクリック後にカウントダウンをクリックした後↓
![スクリーンショット 2022-10-27 120513.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884542/21cc741d-6fcd-89d6-853a-f86ca4fceb4f.png)

2が加算された後に1減算されたことが分かる。

useReducerを使うことでuseStateではできない単体テストができる。そのためバグを事前に防ぐことができる。また、複数名で開発を行う際、useReducerの場合は更新の仕方自体記述されているため、不用意に変更されることがない。