なぜ
ずっと immutable.js
使ってますが、OOP
アプローチに関して、最新何かあるかを探したことろ、immer
が見つかった。なんと、React open source award 2020 の Breakthrough of the year
を受賞されたようです。
どっちが良い
現時点、どっちもメジャーな OOP
アプローチです。immutable.js
は Facebook が管理するライブラリで、結構年数ありました。過去2年のダウンロード数から見ると、最近は immer
が波に乗ってます。サイズやパフォーマンス的にも immer
が良さそうです。
個人感想のメリット
immutable.js
は redux
用のライブラリで、immer
は React.setState
にも使えます。
type
の定義が必要なくて、楽になって、コード量は大きく減ってませんが、可読性が向上したと思います。
変更点 - Settings
redux-immutable
と connected-react-router
の immutable
ライブラリが必要なくなります。
変更点 - Reducer
reducer
から見ると、import
のみ変わって、ほとんど修正必要ありません。
import { handleActions, Action } from 'redux-actions';
import { AppState } from '@domains';
import { ActionTypes } from '@constants';
import { App01Payload, App02Payload } from '@actions/app';
const app = handleActions<AppState, any>(
{
[ActionTypes.APP_PLUS_REQUEST]: (state: AppState) => state,
[ActionTypes.APP_PLUS_SUCCESS]: (state: AppState, { payload: { num } }: Action<App01Payload>) => state.plus(num),
[ActionTypes.APP_PLUS_FAILURE]: (state: AppState) => state,
[ActionTypes.APP_MINUS_REQUEST]: (state: AppState) => state,
[ActionTypes.APP_MINUS_SUCCESS]: (state: AppState, { payload: { num } }: Action<App02Payload>) => state.minus(num),
[ActionTypes.APP_MINUS_FAILURE]: (state: AppState) => state,
},
new AppState()
);
export default app;
import { handleActions, Action } from 'redux-actions';
import { AppState } from '@domains';
import { ActionTypes } from '@constants';
import { App01Payload, App02Payload } from '@actions/app';
const app = handleActions<AppState, any>(
{
[ActionTypes.APP_PLUS_REQUEST]: (state: AppState) => state,
[ActionTypes.APP_PLUS_SUCCESS]: (state: AppState, { payload: { num } }: Action<App01Payload>) => state.plus(num),
[ActionTypes.APP_PLUS_FAILURE]: (state: AppState) => state,
[ActionTypes.APP_MINUS_REQUEST]: (state: AppState) => state,
[ActionTypes.APP_MINUS_SUCCESS]: (state: AppState, { payload: { num } }: Action<App02Payload>) => state.minus(num),
[ActionTypes.APP_MINUS_FAILURE]: (state: AppState) => state,
},
new AppState()
);
export default app;
変更点 - ロジック
従来の typescript type
定義が省略できるので、少し楽になります。書き方も immutable.js
独自の方法じゃなく、ES6
が書けます。
import { Record } from 'immutable';
export interface IApp extends AppProps, Record<AppProps> {
get<K extends keyof AppProps>(key: K): AppProps[K];
}
export interface AppUIProps {}
export interface AppProps extends AppUIProps {
// count
count: number;
}
/**
* App
*/
export default class AppState extends Record<AppProps>({
count: 0,
}) {
plus(num: number) {
return this.set('count', this.count + num);
}
// inner update
minus(num: number) {
return this.set('count', this.count - num);
}
}
import { immerable, produce } from 'immer';
export default class AppState {
[immerable] = true;
count: number = 0;
plus = (num: number) =>
produce(this, (draft) => {
draft.count += num;
});
minus = (num: number) =>
produce(this, (draft) => {
draft.count -= num;
});
}
おまけ
immer
の公式ドキュメントは詳しく色んな情報書いています。
immer
取り込み済みのプロジェクトは GitHub 公開中です。