redux/rematchの日本語の資料がなかったので苦労した

###前置き

reduxが使われているアプリケーションの開発に途中参加しました。管理パッケージにはrematchが使われていて
reduxについて全く知らなかったので調べてみると
Redux Toolkitに関する記事はたくさんありましたが、rematchに関する日本語記事がなく英語弱者なのでちょっと混乱しました。
reduxについて学びながらまとめたメモを、ついでなので記事にしようと思います。
rematchの公式ドキュメントに沿ったメモです。
ソースコードは公式ドキュメントの物です。

公式
- [Rematch|Rematch](https://rematchjs.org/)

---

<!-- - React redux を理解する必要がある。
- editor では左のコンポーネントにホバーした際にも Action が走ってしまっている。よくない気がする。
- 全角空白やセミコロンない箇所は直していい？
  - formarter 掛けた

useSelector でコンポーネントの redux の store にあるデータを読み込み
useDIspatch でコンポーネントのアクションをストアに送信している
Action を Store へ dispatch（送信）
Action を Store に dispatch する手段（store.dispatch()） -->

ざっくりとした Redux

redux は状態管理するためのフレームワーク。正しく使えばイミュータブルにグローバルなステートの管理ができる。

- state(ステート) : 全データを保持するオブジェクト。
- store(ストア) : state を入れる箱。store で管理されているお陰でアプリケーション内のどこからでも state を使えるようになる。
- Action(アクション) : 名前(type)を付けて、変更したい項目を設定できる。
- dispatch(ディスパッチ): Acutionを受け取って state を store に送りつけます。
- reducer(レデューサー): dispatch された Action は Reducer によって処理されます。reducer には受け取った Action によって何を行うか(処理)を書きます。

"state" で作成したオブジェクトを "store"で管理。
更新したい "state" を "Action" で指定する。
"Action" は "dispatch" によって "reducer"に運ばれる。
"reducer"で"Action"を読み取り処理される。
変化させた値は "dispatch" によって "store" に送られる。



## rematch 公式 Getting Startedを読む

<!--
1.  コンポーネントが、Action Creator を呼び出し、Action を取得します。
2.  取得した Action を Reducer に渡します。これを dispatch といいます。
3.  Reducer は渡された Action に応じて State を更新します。
4.  コンポーネントは、State に変更があった場合は、該当の UI を描画し直します。 -->


1. まず createModel を使用してモデルを作成する。モデルは"state の作成","reducer"の作成,"Action の作成"をまとめて行える

   - Model には'state','reduser','Action','async'が包括されている。

   - Remacth のメリットで、これで簡単だよーということらしい。

２. 作成したモデルを init で store にオブジェクトとして作成する

   - npm init や tsc init で Json が生成されるようなものだと思う。

３. Dispatch では createModel で作成した Action を指定して、state を更新して store にしまう。

４. connect なり useSelector なりで表示する

こういうことらしい


## step1 モデルの作成



store に入れたいオブジェクトを作る。
state に初期値を書く
reducers の中に Action を書く、Action の中にそのまま更新されたときの処理を記述
effects は非同期で更新したいときに使う



```ts:count.ts
import { createModel } from '@rematch/core';
import { RootModel } from '.';

export const count = createModel<RootModel>()({
  state: 0, // 初期値
  // 状態変化を処理します　レデューサー関数
  reducers: {
    // ここがクリエイトアクション？
    increment(state, payload: number) {
      return state + payload;
    },
  },
    // 非同期処理はeffects
  effects: (dispatch) => ({
    async incrementAsync(payload: number, state) {
      console.log('これは現在の状態➡', state);
      await new Promise((resolve) => setTimeout(resolve, 1000));
      dispatch.count.increment(payload);
    },
  }),
});
```


```ts:index.ts
import { Models } from '@rematch/core';
import { count } from './count';
export interface RootModel extends Models<RootModel> {
  count: typeof count; // 型を宣言
}

export const models: RootModel = { count };
```



## step2 モデルを store に入れてオブジェクトとして保持



init でモデルの内容を store にオブジェクトとして作成する。npm init や tsc init で Json が生成されるようなものだと思う。

- init に作成した models を入れる。

```ts:store.ts
import { init, RematchDispatch, RematchRootState } from '@rematch/core';
import { models, RootModel } from './models';
export const store = init({
  models,
});
export type Store = typeof store;

export type Dispatch = RematchDispatch<RootModel>;
export type RootState = RematchRootState<RootModel>;
```


## step3 更新の仕方(dispatch)


type に書かれているのがアクション、createModel で reducer に書いたやつがアクション
payload は送る値
dispatch ({type: "モデル名/アクション名",payload: 値})

```ts
const { dispatch } = store;
// state = { count: 0 }
// reducers
dispatch({ type: 'count/increment', payload: 1 }); // state = { count: 1 }
dispatch.count.increment(1); // state = { count: 2 }

// effects
dispatch({ type: 'count/incrementAsync', payload: 1 }); // state = { count: 3 } after delay
dispatch.count.incrementAsync(1); // state = { count: 4 } after delay
```

## step4 表示

表示に関してはrematchは特に関係ないみたい。
connectを使って書かれているが、useSelectedを使うのが主流。

```ts
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider, connect } from 'react-redux';
import store from './store';
const Count = (props) => (
  <div>
    The count is {props.count}
    <button onClick={props.increment}>increment</button>
    <button onClick={props.incrementAsync}>incrementAsync</button>
  </div>
);
const mapState = (state) => ({
  count: state.count,
});
const mapDispatch = (dispatch) => ({
  increment: () => dispatch.count.increment(1),
  incrementAsync: () => dispatch.count.incrementAsync(1),
});
const CountContainer = connect(mapState, mapDispatch)(Count);
ReactDOM.render(
  <Provider store={store}>
    <CountContainer />
  </Provider>,
  document.getElementById('root')
);
```
---
英語がわかれば簡単だったな～って思いました。
toolkitと比較できるほど理解が進んでないのですが、別段機能に違いはない印象です。
いまから使うならtoolkitのほうがいいですね。