stateの管理をReactからReduxに書き換える

# はじめに

前々からインターン先でReactを書いていましたがReduxに触ることはなかったです。

ただ自分でも勉強していた時期があったのですが、Reduxのflowと亜種の多さに負けて取り組めないでいました。

しかし9月から働き始めたインターン先でReduxを書かなければならなかったので、早急にキャッチアップをしました。最初はかなり躓きましたが、なんとか実装し切ることが出来ました。それでも、まだ整理しきれてなかったので今回まとめてみました。

Reduxの組み合わせは様々ですが、今回はデファクトスタンダードになりつつある？Redux　toolkitを使用しました。


またReduxを使わずにuseStateで管理したものも作ったので、そちらと照らし合わせながら読んでもらえると理解が深まるかもです。


## 今回のデモアプリ

![Qhf744SCqNpZzD3KOYPO1633272030-1633272176.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481470/bea14464-02a1-e708-503b-73d8422b00f8.gif)

> Reactのみのコード
code：https://codesandbox.io/s/jian-yi-huiruta-ver-react-lmkro?file=/src/hooks/useAllUsers.tsx:244-257
app：https://lmkro.csb.app/

> Reduxを使用したコード
code：https://codesandbox.io/s/jian-yi-huiruta-ver-redux-nqk1k?file=/src/index.tsx
app：https://nqk1k.csb.app/


## 開発環境
| ライブラリ |   バージョン     |   
|---:|-------------|
| React  |    17.0.2         |          
| Redux toolkit  |1.5.1|      
| typescript |4.1.5|      
| mui/material |5.0.1|      

# 異なる点

## stateの設定方法

まずはstateの設定方法です。Reactであれば```useState```を用いることで簡単に出来ます。


**useStateを使用した場合**

```ts
export type isUser = {
  1: boolean;
  2: boolean;
  3: boolean;
};


 const [modalUser, setModalUser] = useState<isUser>({
    1: true,
    2: true,
    3: true,
  });

  const [displayUser, setDisplayUser] = useState<isUser>({
    1: true,
    2: true,
    3: true,
  });
```

これをReduxで同じことを行うと以下のようになります。(今回はdispalyUserのみReduxで管理し、modalUserはReact同様コンポーネントで保持しています。)

**Redux toolkitを使用した場合**

```tsx:SetUserSlice.tsx
import { createSlice, PayloadAction } from '@reduxjs/toolkit';

export type isUser = {
  1: boolean;
  2: boolean;
  3: boolean;
};

export type isUserType = {
  displayUser: {
    1: boolean;
    2: boolean;
    3: boolean;
  };
};


const initialState: isUserType = {
  displayUser: {
    1: true,
    2: true,
    3: true,
  },
};

export const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {},
});

// action creatorsをエクスポート
export const { setDisplayUser } = userSlice.actions;

//reducerをエクスポート
export default userSlice.reducer;
```

```tsx:store.tsx
export const store = configureStore({
  reducer: { user: userReducer },
});
```

これで同じように```displayUser```の初期値を設定することが出来ました。

それでは試しにトップレベルの``App.tsx``で呼び出してみましょう。

Redux　toolkitでstateを参照するときは```useSelector```を使います。

```tsx:App.tsx
const displayUser = useSelector((state: RootState) => state.user.displayUser)
console.log(displayUser)
// => {1: true, 2: true, 3: true}
```

これでuseStateで設定した時と同じようにstateを使うことが出来ます。


## stateの更新方法

次にstateの更新方法です。

今回はモーダルの``適用ボタン``が押された時に走る処理に着目したいと思います。

**useStateを使用した場合**

```tsx:App.tsx
  const onSubmitModal = (modalUser: isUser) => {
    setDisplayUser({
      ...modalUser,
    });
    isModalOpen(); // モーダルを閉じる関数
  };
```

```setDispalyUser```の中は[スプレッド構文](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax) と呼ばれる方法で同じ名前のプロパティに上書きを実行しています。ピンとこない人は下のことを同じことをやっているんだぁと思ってもらえたら大丈夫です。

```tsx
setDisplayUser({
   1: modalUser[0]
   2: modalUser[1]
   3: modalUser[2]
});
```

次はこれと同じことをReduxでやってみます。ここは少しわかりづらくなるかもです。


```tsx:setUserSlice.tsx
export const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {
    setDisplayUser: (state, { payload }: PayloadAction<isUser>) => {
      return { ...state, displayUser: payload };
    },
  },
});
```

```tsx:App.tsx
const onSubmitModal = () => {
  dispatch(setDisplayUser({ ...modalUser }));
  isModalOpen();
};
```

ここで新しく``reducers``と``dispatch``という単語が出てきましたが、
```reducers```は、```useState```の第二引数に入る```set~~~```にあたる部分だとイメージしてもらうのがわかりやすいと思います。



```dispatch ``` に関しては ```reducers```を使って更新する際に使うものです。

> ```reducers```と```dispatch ```などReduxは色んな単語が出てきます。最初からそれを全部覚えるのはシンドいので使いながら理解を深めていくのがおすすめです。


このように
1. reducersにstateを更新する関数を書く
2. その関数をdispatchを使って呼ぶ

という手順でstateを更新することができます。


# まとめ

どうにかしてReduxを動かしたいという方の助けになればと思って書きました。最初からすべて理解するのは大変なので、色々なコードをたくさん見て、自分の手元で動かしながら学習していくのがいいと思います。

自分もまだまだ未熟なので今後精進していきたいと思います。



## 参考文献

この記事は以下の情報を参考にして執筆しました。

- [React + Typescript プロジェクトに Redux Toolkit を導入したので使い方をざっくりとまとめてみる](https://dev.classmethod.jp/articles/react-typescript-redux-toolkit/)
- [HookとRedux ToolkitでReact Reduxに入門する](https://www.hypertextcandy.com/learn-react-redux-with-hooks-and-redux-starter-kit#redux-toolkit-%E3%81%AE%E7%99%BB%E5%A0%B4)
- [Redux Toolkit入門](https://zenn.dev/mayamashita/articles/12ab4a122a02cc)