reactive と ref の基本
Vue 3のComposition APIでデータのリアクティビティを実現するためのメソッドに
reactiveとrefがあります。これらを使用して作成されたデータはリアクティブになり、変更を監視することができます。
reactiveとrefにおけるリアクティビティのはまりポイント
オブジェクトへの新しいプロパティの追加
reactive
やrefで作成されたオブジェクトに新しいプロパティを動的に追加する場合、そのプロパティはリアクティブではありません。初期化時にreactive
に渡されたオブジェクトのプロパティのみがリアクティブに監視されます。
const state = reactive({ a: 1 });
state.b = 2; // リアクティビティがない
解決策
reactive
やref
でラップされたオブジェクトに新しいプロパティを追加する際、新しいオブジェクトを生成してスプレッド演算子を使用することで、新しいプロパティも含めてリアクティブなオブジェクトを取得することができます。
const state = reactive({ a: 1 });
state = { ...state, b: 2 }; // 新しいプロパティbを追加
const refState = ref({ x: 1 });
refState.value = { ...refState.value, y: 2 }; // 新しいプロパティyを追加
toRefsを使用することでreactive
オブジェクトの各プロパティを個別のref
として取得することもできます。reactive
オブジェクトを新しいオブジェクトとマージすることで、新しいプロパティもリアクティブに保つことができます。
import { reactive, toRefs, ref } from 'vue';
const state = reactive({ a: 1 });
const refs = toRefs(state);
const newState = { ...refs, b: ref(2) }; // 各プロパティがrefとして展開され、新しいプロパティbも追加
console.log(newState.a.value) // 1
console.log(newState.b.value) // 2
ref
でラップされたオブジェクトの中身を更新する場合、直接ref
を再代入するのではなく、.value
を使って更新することで、オブジェクトのリアクティブ性を維持することができます。
import { ref } from 'vue';
const obj = ref({ prop: 'initial' });
obj.value.prop = 'updated'; // 正しい方法でプロパティを更新
console.log(obj.value); // { prop: 'updated' }
// 間違った方法
obj = ref({ prop: 'new object' }); // これはobj全体を再代入してしまっている
console.log(obj.value); // { prop: 'new object' }
console.log(obj.value.prop); // 'new object'
下記はobj
に新しいref
オブジェクトを再代入しています。したがって、obj
は新しいref
オブジェクトを指すようになり、以前のref
オブジェクトへの参照を失います。
// 間違った方法
obj = ref({ prop: 'new object' }); // これはobj全体を再代入してしまっている
まとめ
Vue 3のComposition APIはreactive
とref
の使い分けが難しい上にオブジェクトのリアクティビティには注意点がいくつか存在します。
効果的に使っていきたいものです。。