###前置き
reduxが使われているアプリケーションの開発に途中参加しました。管理パッケージにはrematchが使われていて
reduxについて全く知らなかったので調べてみると
Redux Toolkitに関する記事はたくさんありましたが、rematchに関する日本語記事がなく英語弱者なのでちょっと混乱しました。
reduxについて学びながらまとめたメモを、ついでなので記事にしようと思います。
rematchの公式ドキュメントに沿ったメモです。
ソースコードは公式ドキュメントの物です。
公式
ざっくりとした 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を読む
-
まず createModel を使用してモデルを作成する。モデルは"state の作成","reducer"の作成,"Action の作成"をまとめて行える
-
Model には'state','reduser','Action','async'が包括されている。
-
Remacth のメリットで、これで簡単だよーということらしい。
-
2. 作成したモデルを init で store にオブジェクトとして作成する
- npm init や tsc init で Json が生成されるようなものだと思う。
3. Dispatch では createModel で作成した Action を指定して、state を更新して store にしまう。
4. connect なり useSelector なりで表示する
こういうことらしい
step1 モデルの作成
store に入れたいオブジェクトを作る。
state に初期値を書く
reducers の中に Action を書く、Action の中にそのまま更新されたときの処理を記述
effects は非同期で更新したいときに使う
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);
},
}),
});
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 を入れる。
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: 値})
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を使うのが主流。
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のほうがいいですね。