MobXの@computedと@computed.structの違いついて調べた
@computedと@computed.structはどちらも、MobXで派生データ(他のobservableに基づく値)を効率的に計算・キャッシュするために使用されるデコレータ
ただし、@computedの場合、再計算のトリガーは、直前の計算結果と新しい結果の===(参照比較)で異なると判断されたときになる
一方で、@computed.structは深い構造の比較(構造的比較)を行って、結果が異なるかどうかを判断する
そのため、オブジェクトや配列のような複雑なデータ構造を計算した結果でも、内容が同一であれば再計算をトリガーしないこと@computed.structの特徴
例
import { observable, computed } from 'mobx'; class Store { @observable items = [{ name: 'apple', price: 10 }]; @computed.struct get itemList() { return this.items.map(item => ({ ...item })); } } const store = new Store(); const firstCall = store.itemList; console.log(firstCall); // [{ name: 'apple', price: 10 }] store.items = [{ name: 'apple', price: 10 }]; // 同じ内容で再代入 console.log(firstCall === store.itemList); // true (内容が同じなので再計算されない)
@computedと@computed.structの主な違い
| 特徴 | @computed |
@computed.struct |
|---|---|---|
| 比較方法 | 参照比較(===) |
構造比較(深い内容の比較) |
| 再計算のトリガー | 新旧の計算結果が異なる参照を持つ場合 | 新旧の計算結果が異なる構造を持つ場合 |
| 適用対象 | プリミティブ値や参照比較で十分な場合 | オブジェクトや配列など構造の比較が必要な場合 |
| パフォーマンス | 参照比較なので通常速い | 構造比較により比較処理が増加する可能性あり |
使い分け
@computed- プリミティブ値(数値や文字列)の計算結果
- 参照が変わったかどうかで十分に結果を判断できる場合
- 例: 合計値、単純な文字列の結合
@computed.struct- オブジェクトや配列を返す計算結果
- 計算結果が同じ内容の異なる参照であっても、再計算を抑制したい場合
- 例: 深い比較が必要な場合(データの内容が変わらない限り、再計算を避けたい)。
注意点
@computed.structのパフォーマンスコスト- 構造比較を行うため、計算結果が巨大なオブジェクトや深いネストを持つ場合、比較コストが増加する可能性がある
- 頻繁に再計算される状況では、適切に使うことで無駄な再計算を抑える
- 適用箇所を吟味する
- 基本的に
@computedを使い、必要に応じて@computed.structを選択する
- 基本的に
まとめ
@computedは参照比較を用いて効率的に計算結果をキャッシュする@computed.structは構造比較を用いて、内容が同じであれば無駄な再計算を防ぐ- 配列やオブジェクトを返す計算が多い場合、
@computed.structを適切に活用するとパフォーマンス向上が見込める