Vue 3でプリミティブな値(数値や文字列)をリアクティブにするために推奨される関数はどれか?
解説
Vue 3でプリミティブ値をリアクティブにするならref()が正解ですが、ポイントはなぜreactive()ではダメなのかを理解することです。ref()は内部で値を{ value: ... }というオブジェクトにラップすることで、プリミティブ値でもリアクティビティを実現しています。ref()とreactive()は何が違うのかreactive()はオブジェクトや配列をリアクティブにする関数ですが、プリミティブ値(number、string、boolean)には使えません。JavaScriptの仕組み上、プリミティブ値は参照ではなく値そのものがコピーされるため、Proxyで変更を検知できないのです。一方ref()はプリミティブ・オブジェクト両方に対応するため、Vue 3公式ドキュメントでもref()で統一するスタイルが推奨されています。import { ref, reactive } from 'vue' // ref: プリミティブもオブジェクトもOK const count = ref(0) const user = ref({ name: 'Alice' }) // reactive: オブジェクトのみ const state = reactive({ count: 0, name: 'Alice' }) // reactive(0) // これは動作しないstate()はVue 3に存在しない関数です。ReactのuseStateと混同しやすいので注意してください。computed()は他のリアクティブな値から派生した読み取り専用の値を定義する関数であり、状態を保持する目的には使いません。.valueアクセスの仕組みと注意点ref()で作成した値は、<script>内では.valueを通じてアクセスする必要があります。これはプリミティブ値をオブジェクトでラップしているためです。ただし<template>内ではVueが自動的にアンラップするため、.valueは不要です。<script setup> import { ref } from 'vue' const count = ref(0) function increment() { count.value++ // scriptでは.valueが必要 } </script> <template> <!-- templateでは.value不要 --> <button @click="increment">{{ count }}</button> </template>初学者がよくやるミスは、script内で.valueを付け忘れることです。エラーにはならず値が更新されないため、原因特定に時間がかかりがちです。reactiveの分割代入で壊れるリアクティビティreactive()を使う場合、分割代入するとリアクティビティが失われるという落とし穴があります。これもref()が推奨される理由の一つです。const state = reactive({ count: 0, name: 'Alice' }) // リアクティビティが切れる let { count } = state count++ // stateには反映されない // refなら関数間の受け渡しでも安全 const count = ref(0) useCounter(count) // リアクティビティが維持される実務でのref統一スタイル公式推奨: Vue 3.4以降の公式ドキュメントでは、シンプルさと一貫性の観点からref()で統一するスタイルが推奨されているコンポーザブル関数: refは関数の引数や戻り値として渡してもリアクティビティが保たれるため、再利用可能なロジック(composable)との相性が良いtoRefs()との併用: reactiveを使う場面でもtoRefs()でrefに変換すれば、分割代入しても安全に扱える