Redux / Redux-Toolkitについて

# 🔮 はじめに
Reactの状態管理ライブラリでよく使用されるReduxについて少し勉強したため．忘備録として簡単にまとめます．

# 🔮 自己紹介
初めまして．趣味でweb開発を勉強している273*(ﾂﾅｻﾝﾄﾞ) / Kei.と申します．関西の大学生です．最近はフルスタック開発やツール制作を行なっています．初心者です．

# 🔮 本題

## Redux
公式ドキュメント
https://redux.js.org/

ReactのuseStateのように状態を管理するもの．useStateはコンポーネント単位でしか管理できないが，Reduxはアプリ全体で状態を管理(一元管理)するツールである．他のフレームワークでも利用可能．Redux Toolkitの使用が推奨されているので，ここではそれを使用する．

- 「**グローバルストア**」と呼ばれる場所で**状態(state)** を一括管理する．
- 状態を直接変更するのではなく，**アクション(action)** を通じて**どう変えるかをReducerで定義**する．

RecoilやZustand，Jotaiなど状態管理ライブラリは色々ある．
RecoilはReduxより簡単だが開発が止まっているため推奨しない．
Jotaiは日本人が作っている．

## Redux Toolkit
公式ドキュメント
https://redux-toolkit.js.org/

Redux Toolkit とは，アプリケーションの状態管理をする Redux をより簡単に扱えるようにしたライブラリ．公式もこちらの仕様を推奨している．

## 基本用語

### Store
- アプリ全体の状態を保持する．Reduxの中心的な存在．
- 各コンポーネントはストアから状態を取得したり，更新を依頼する．
```Javascript
import { configureStore } from "@reduxjs/toolkit";
const store = configureStore({
  reducer: {
    user: userReducer,
    channel: channelReducer,
  } 
});
```

### State
- ストアに保存されているデータそのもの．
- アプリ全体の「現在の状態」を表す．
```Javascript
const initialState: InitialChannelState = {
  channelId: null,
  channelName: null,
};
```

### Action
 - 状態を変更するために送る指示．Acrion Createrで生成される．
```json
// acrionの例．JSONに似たJavaScriptオブジェクト
{
  "type": "user/setName", // アクションの種類を示す
  "payload": "Bob" // 必要に応じてデータを含む
}
```

### Dispatch
- アクションをストアに送るためのメソッド．
- アクションがディスパッチされるとReducer が呼び出され，状態が更新されます。
```Javascript
dispatch(setName("Bob"))}
dispatch({ type: "user/setName", payload: "Bob" });
```
### Reducer
- アクションを受け取り，新しい状態を計算する純粋関数．
- 現在の状態とアクションを引数に取り，新しい状態を返す．
```Javascript
reducers: {
  login: (state, action) => {
    state.user = action.payload;
  },
    logout: (state) => {
    state.user = null;
  },
}
```

### Selector
- ストアから必要なデータを取り出すための関数．
- コンポーネントで `useSelector` を使ってアクセスする．
```Javascript
const userName = useSelector((state) => state.user.name);
```

### Slice
- state，Reducer，action creatorをまとめたもの
```javascript
// 買い物かごの初期化

const initialState = {
  cartItem: [], // 商品リスト
  amount: 0, // 合計個数
  total: 0, // 合計金額
};

const cartSlice = createSlice({
  name: "cart", // sliceの名前 useSelectorで参照するときに使う
  initialState, // 初期値
  reducers: {}, // action creatorが含まれている(自動生成)
});
```

### Provider
- Storeをどのコンポーネントからも使えるようにするもの．
```js
import { Provider } from "react-redux";
import { store } from "./redux/store";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);
```

## 動作の流れ

1. ユーザが操作する．
   ：ボタンをクリックしたりフォームを送信したりなど，イベントをトリガーする．
2. Actionが生成される．
   ：ユーザの操作に応じて`Action Creator`がアクションを生成する．
   ：ユーザの操作に応じて「何をしたいか（アクション）」を作るのがAcrion Creater．
```javascript
// Action Createrとaction
const setName = (name) => ({
  type: "user/setName",
  payload: name,
});

```
3. Dispatch でアクションをストアに送る
   ：アクションが `dispatch` を通じてストアに送られる．
```javascript
dispatch(setName("Bob"));
```
4. Reducer が新しい状態を計算する
   ：ストアは Reducer を呼び出し，アクションに応じて新しい状態を計算する
5. ストアの状態が更新される
   ：新しい状態がストアに保存される
6. UIがレンダリングされる

## イメージ
![入門編】Reduxによる状態管理の仕組みを理解する](https://storage.googleapis.com/zenn-user-upload/92alq46m4gh0v1sprqgf46m3f38r)

https://redux.js.org/tutorials/essentials/part-1-overview-concepts#redux-application-data-flow

![Reduxの用語と使い方についてまとめました【React/React-redux/Redux Toolkit】 | えむ家のメモ帳](https://m-kenomemo.com/wp/wp-content/uploads/2023/01/m-kenomemo20230111.png)

https://m-kenomemo.com/redux-term/

## Redux Toolkitを用いた状態管理の例

- ストアの設定
```javascript
import { configureStore } from "@reduxjs/toolkit";
import userReducer from "./userSlice";

// ストアの作成
const store = configureStore({
  reducer: {
    user: userReducer, // reducerの設定
  },
});

export default store;

```
- スライスの作成
```javascript
import { createSlice } from "@reduxjs/toolkit";

const userSlice = createSlice({
  name: "user", // スライス名
  initialState: { name: "Alice" }, // stateの初期値
  // stateの更新処理
  reducers: {
    setName: (state, action) => {
      state.name = action.payload;
    },
  },
});

// action creater を作成してエクスポート
export const { setName } = userSlice.actions;
export default userSlice.reducer;

```
- Reactコンポーネントで使用
```javascript
import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { setName } from "./userSlice";

const UserComponent = () => {
  // useSelectorで現在のstateを取得
  // state.userのuserはreducerで定義したオブジェクトのuserプロパティのこと
  const name = useSelector((state) => state.user.name);
  // 以下のようにactionをdispatchでストアに送る
  const dispatch = useDispatch();

  return (
    <div>
      <p>User Name: {name}</p>
      <button onClick={() => dispatch(setName("Bob"))}>
        Change Name
      </button>
    </div>
  );
};

export default UserComponent;

```

## 🔗 参考文献
https://qiita.com/ryocha12/items/76acbf02e9e73bb0c5ec

https://redux.js.org/tutorials/essentials/part-1-overview-concepts#redux-application-data-flow

https://m-kenomemo.com/redux-term/

# 🔮 最後に
Redux / Redux-Toolkitについてまとめてみました！誰かの参考になったら幸いです．最後まで読んでいただきありがとうございました．それでは！