モデルにImmutable.JSを使用する利点
Immutable.JS使ってますか? よくある記事では不変的なオブジェクトを扱えるばかり注目されてますが、それ以外にも便利な機能があります.
Immutable.Record
は特にオススメです.
Record
を使えばモデルの設計が捗ります.
自分はImmutable.JSをReact & Flux等のStoreの管理に利用してます.
当初は愚直にupdateを書きまくって管理してたのですが複雑になりすぎて、これは良くないと再設計し直しました.
その再設計の中心にRecord
でモデルを作成して#mergeDeepWith
を使ってStoreを更新する方法です.
CodePenにサンプルを用意したので参考にしてください.
See the Pen Use model layer with Immutable.JS by satoruk (@satoruk) on CodePen.
サンプルコードの解説
Define User model
変数defaultValues
Userモデルのデフォルト値兼プロパティ定義です.
このオブジェクトのプロパティに無いプロパティはUserインスタンスで無視されます.
defaultValues
の値は必ず全てundefined
を指定する様にします
理由は#mergeDeepWith
する際にundefined
値のマージをスキップするためです.
get age()
User#age
は生年月日(DOB)からmoment
を使って年齢を計算しています.
普通にプロパティっぽく参照できますし、get
修飾子を無くせばただのメソッドです.
create users
以下の様にすることでモデルのオブジェクトを取得できます.
friends
にImmutable.Map()
を利用している理由はImmutable.List()
等では#mergeDeepWith
を利用したマージの際に不都合があるからです.
コンポジットな関係の場合はImmutable.Map()
系統を使うのが無難です.
const carol = new User({
id: 1002,
name: 'Carol',
dob: moment('1997-06-01T00:00:00+00:00'),
friends: Immutable.Map().set(alice.id, alice.id),
});
Initialize state and funcs
#mergeDeepWith
で差分を取り込む際に以下の関数を使用します.
この関数が要で、ネストした構造をこれ一発でマージする様にしています.
const merger = (old, v) => (_.isUndefined(v) ? old : v);