Redux with React

# 前置き
この記事では、ReactアプリケーションでReduxを使用する方法をまとめています。
ただし、ReduxはReactに特化したライブラリではなくJavaScriptのアプリケーションのためのライブラリであるため、まず純粋なReduxについてざっくり解説した後、Reactアプリケーションと一緒に使用する方法を解説します。

※ Qiitaの記事を書いていて、途中うまく書けなくなって断念することが多いので、未完成の状態でもとりあえず投稿しています。この文があるということは、未完成で編集中 or 諦めたのどちらかと考えてください。


# Redux
## Reduxとは？
JavaScriptアプリケーションのためのGlobal Stateを管理するためのライブラリ。
StoreにGlobal Stateを保存し、決められた方法でのみ値を取得・更新することができる。

## Reduxのインストール
公式がRedux Toolkit（Redux coreとReactアプリの作成に便利な関数等をまとめたパッケージ）の仕様を推奨しているため、そのインストール方法を紹介。
```shell
npm install @reduxjs/toolkit
```
※ その他の導入方法は[こちら](https://redux.js.org/introduction/getting-started#installation)

## Reduxで知っておくべき用語
**store**
現在のstateを保存しているオブジェクト。

**action**
typeプロパティを持つオブジェクトで、storeに対してstateを更新するように依頼するために使用される。
他にもstateを変更するために使用する値を持たせる。（payloadをキーに設定することが多い）

**action creator**
actionを返す関数で、毎回アクションを記述するコストを減らすために記述される。

**reducer**
現在のstateとactionを引数に取り、新しいstateを返す関数。
reducerのルールは以下の通り
* 新しいstateを計算するのに、現在のstateとaction以外の値を使用してはいけない。
* 現在のstateを変更してはいけない。
* 非同期処理、ランダムな値の計算、その他の副作用を発生させる計算を行ってはいけない。

**dispatch**
storeが持つ関数で、stateを更新する唯一の方法。
actionを引数に持ち、そのアクションをreducerに渡してstateの変更を行う。

**selector**
特定のstateを取得するための関数。

## Reduxの仕組み
![Reduxの仕組み.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303693/1a8165c2-724a-cc1c-05ce-f4936405890e.png)
### storeの作成
createStore関数かconfigureStore関数のどちらかを使って作成。

### storeから値の取得
以下のように、storeクラスのgetStateメソッドを使用して値を取得。
```javascript
const state = store.getState()
const value = state.someKey.valueKey   // someKey,valueKeyは適切なオブジェクトのプロパティを使用
```
ただし、毎回記述するのが大変なため、以下のようにselector定義・使用するのが多い。
```javascript
const selectValue = state => state.someKey.valueKey   // someKey,valueKeyは適切なオブジェクトのプロパティを使用
const value = selectValue(store.getState())
```

### storeの値を変更する
storeの値を変更する方法は以下の3stepです。
1. dispatch関数にactionを渡す。
2. actionの値と現在のstateに基づいて、reducerが新しいstateを返す。
3. reducerの返した値がstateに保存される。

# ReactでReduxを使用する方法
## 導入
ReduxをReactアプリケーションで使用する場合、Redux Toolkitに加えてreact-reduxパッケージを使用する。
```shell
npm install react-redux
```
## ReactでReduxを使用する
[Redux公式チュートリアルPart 2](https://redux.js.org/tutorials/essentials/part-2-app-structure)で紹介されている方法を紹介する。
手順は以下の通り。
1. sliceの作成
2. storeの作成
3. Reactアプリにstoreを導入
4. stateの取得
5. stateの更新

### sliceの作成
createSlice関数（from '@redux/toolkit'）を使用してsleceを作成する。

※ sliceは、Reducerのロジック・actionがを含んだオブジェクト（型は以下の通り）
```typescript
{
    name: string
    reducer: ReducerFunction
    actions: Record<string, ActionCreator>
    caseReducers: Record<string, CaseReducer>
    getInitialState: () => State
}
```

### storeの作成
configureStore関数（from '@redux/toolkit'）を使用してstoreを作成

### Reactアプリにstoreを導入
Proveiderコンポーネント（from 'react-redux'）を使用してコンポーネントツリー内からstoreにアクセスできるようにする。

### stateの取得
useSelector hook（from 'react-redux）を使用使用することで、Provider以下のコンポーネント内でstateを取得する。

### stateの更新
useDispatch hook（from 'react-redux）を使用することで、Provider以下のコンポーネント内でstore.dispatchが使用できるようになる。

# API＋便利な使い方
## createSlice
### 型情報
```typescript
type CreateSliceType = (ArgObjectType) => ReturnObjctType
type ArgObjectType = {
  name: string        
  initialState: any,
  reducers: Object<string, ReducerFunction | ReducerAndPrepareObject>
  extraReducers?: Object<string, ReducerFunction> | ((builder: ActionReducerMapBuilder<State>) => void)
}
type ReturnObjctType = {
  name: string
  reducer: ReducerFunction
  actions: Record<string, ActionCreator>
  caseReducers: Record<string, CaseReducer>
  getInitialState: () => State
}
```