Vue.js 3のComposition API完全ガイド!Reactユーザーでも5分で理解できる実践的な使い方

Vue.js 3のComposition APIとは
Vue.js 3で導入されたComposition APIは、コンポーネントのロジックをより柔軟に記述できる新しいAPIです。従来のOptions API(data、methods、computedなどを分けて書く方式)とは異なり、すべてのロジックをsetup関数内にまとめて記述できます。
// Options API(従来の書き方)
export default {
data() {
return {
count: 0
}
},
methods: {
increment() {
this.count++
}
}
}
// Composition API(新しい書き方)
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
const increment = () => count.value++
return {
count,
increment
}
}
}
最大のメリットは、関連する機能をまとめて書けることです。大きなコンポーネントでも、ユーザー管理、商品管理などの機能ごとにコードをグループ化できるため、保守性が格段に向上します。
ReactのHooksとの違いと共通点
Reactの経験がある方なら、Composition APIはHooksにとても似ていることに気づくでしょう。どちらもコンポーネントのロジックを関数ベースで書く仕組みです。
// React Hooks
import { useState, useEffect } from 'react'
function Counter() {
const [count, setCount] = useState(0)
useEffect(() => {
document.title = `Count: ${count}`
}, [count])
return (
<button onClick={() => setCount(count + 1)}>
{count}
</button>
)
}
// Vue Composition API
import { ref, watchEffect } from 'vue'
export default {
setup() {
const count = ref(0)
watchEffect(() => {
document.title = `Count: ${count.value}`
})
return {
count,
increment: () => count.value++
}
}
}
主な違いは以下の通りです:
- リアクティビティ: Vueはrefやreactiveでリアクティブなデータを明示的に作成します
- 再実行の仕組み: ReactのHooksは再レンダー時に毎回実行されますが、VueのComposition APIは一度だけ実行されます
- 依存配列: Reactのように依存配列を手動で管理する必要がなく、Vueが自動で追跡してくれます
基本的なsetupの書き方と実装例
setup関数はComposition APIの入り口です。ここでリアクティブなデータや関数を定義し、テンプレートで使用するものをreturnします。
import { ref, computed, onMounted } from 'vue'
export default {
setup() {
// リアクティブなデータ
const message = ref('Hello Vue 3!')
const todos = ref([])
// 算出プロパティ
const todoCount = computed(() => todos.value.length)
// メソッド
const addTodo = (text) => {
todos.value.push({
id: Date.now(),
text,
completed: false
})
}
// ライフサイクルフック
onMounted(() => {
console.log('コンポーネントがマウントされました')
})
// テンプレートで使用するものを返す
return {
message,
todos,
todoCount,
addTodo
}
}
}
重要なポイントは、refで作成したリアクティブな値にアクセスする際は.value
を使うことです。テンプレート内では自動的にアンラップされるので.value
は不要ですが、JavaScript内では必須です。
よく使うComposition API関数の実践例
実際の開発でよく使用されるComposition API関数とその使い方を紹介します。
ref vs reactive
プリミティブな値にはref、オブジェクトにはreactiveを使います:
import { ref, reactive } from 'vue'
export default {
setup() {
// プリミティブ値にはref
const count = ref(0)
const isLoading = ref(false)
// オブジェクトにはreactive
const user = reactive({
name: '田中太郎',
age: 25,
email: '[email protected]'
})
return { count, isLoading, user }
}
}
watch と watchEffect
データの変更を監視する2つの方法があります:
import { ref, watch, watchEffect } from 'vue'
export default {
setup() {
const searchQuery = ref('')
const results = ref([])
// 特定の値を監視(React useEffectの依存配列に近い)
watch(searchQuery, async (newQuery) => {
if (newQuery) {
results.value = await searchAPI(newQuery)
}
})
// 自動的に依存関係を追跡
watchEffect(() => {
// この中で使用したリアクティブな値が変更されると自動実行
console.log(`検索キーワード: ${searchQuery.value}`)
})
return { searchQuery, results }
}
}
カスタムフック(composables)
ロジックを再利用可能な関数として切り出せます:
// useCounter.js
import { ref } from 'vue'
export function useCounter(initialValue = 0) {
const count = ref(initialValue)
const increment = () => count.value++
const decrement = () => count.value--
const reset = () => count.value = initialValue
return {
count,
increment,
decrement,
reset
}
}
// コンポーネント内で使用
import { useCounter } from './useCounter'
export default {
setup() {
const { count, increment, decrement } = useCounter(10)
return {
count,
increment,
decrement
}
}
}
既存のOptions APIからの移行方法
既存のOptions APIコンポーネントをComposition APIに移行する際のパターンを理解しておきましょう。幸い、両者は同じコンポーネント内で併用できるので、段階的な移行が可能です。
基本的な変換パターン
// Options API(移行前)
export default {
data() {
return {
name: '',
email: '',
isSubmitting: false
}
},
computed: {
isValid() {
return this.name && this.email
}
},
methods: {
async submit() {
this.isSubmitting = true
try {
await this.saveUser()
} finally {
this.isSubmitting = false
}
},
async saveUser() {
// API呼び出し
}
},
mounted() {
this.loadUserData()
}
}
// Composition API(移行後)
import { ref, computed, onMounted } from 'vue'
export default {
setup() {
const name = ref('')
const email = ref('')
const isSubmitting = ref(false)
const isValid = computed(() => name.value && email.value)
const saveUser = async () => {
// API呼び出し
}
const submit = async () => {
isSubmitting.value = true
try {
await saveUser()
} finally {
isSubmitting.value = false
}
}
const loadUserData = () => {
// ユーザーデータの読み込み
}
onMounted(() => {
loadUserData()
})
return {
name,
email,
isSubmitting,
isValid,
submit
}
}
}
段階的移行のコツ
一度にすべてを移行する必要はありません。新しい機能はComposition APIで書き、既存部分は必要に応じて移行していくのが効率的です:
export default {
// 既存のOptions API
data() {
return {
oldFeature: 'これは残しておく'
}
},
// 新しいComposition API
setup() {
const newFeature = ref('新機能はこちらで')
return {
newFeature
}
}
}
トラブルシューティングとベストプラクティス
Composition APIを使用する際によく遭遇する問題と解決策をまとめました。
よくあるエラーと解決法
- 「Cannot read property 'value' of undefined」エラー
// ❌ NGパターン
export default {
setup() {
let count // refを使っていない
const increment = () => {
count.value++ // エラー:countはundefined
}
return { count, increment }
}
}
// ✅ OKパターン
export default {
setup() {
const count = ref(0) // refで作成
const increment = () => {
count.value++
}
return { count, increment }
}
}
- リアクティビティが効かない問題
// ❌ NGパターン
const user = reactive({
name: '田中太郎'
})
// オブジェクトを分割代入すると reactivity が失われる
const { name } = user
name = '佐藤花子' // リアクティビティが効かない
// ✅ OKパターン
const user = reactive({
name: '田中太郎'
})
// toRefsを使って分割代入
const { name } = toRefs(user)
name.value = '佐藤花子' // 正しく動作
ベストプラクティス
- 関数の命名規則を統一する
composable関数は use
で始める慣習があります:
// ✅ 良い例
export function useUserAuth() { /* ... */ }
export function useLocalStorage() { /* ... */ }
// ❌ 避けたい例
export function authManager() { /* ... */ }
export function storage() { /* ... */ }
- setup関数内でのthis使用を避ける
// ❌ NGパターン
export default {
setup() {
const doSomething = () => {
console.log(this) // undefinedになる
}
}
}
// ✅ OKパターン
export default {
setup(props, { emit }) {
const doSomething = () => {
emit('custom-event') // 正しい方法
}
}
}
- メモリリークを避ける
export default {
setup() {
const timer = ref(null)
onMounted(() => {
timer.value = setInterval(() => {
console.log('定期実行')
}, 1000)
})
// 重要:コンポーネント破棄時にクリーンアップ
onBeforeUnmount(() => {
if (timer.value) {
clearInterval(timer.value)
}
})
return {}
}
}
これらのポイントを押さえることで、Composition APIを安全かつ効率的に活用できます。Vue.js 3の新機能を存分に活用して、よりメンテナンスしやすいコードを書いていきましょう!
このトピックはこちらの書籍で勉強するのがおすすめ!
この記事の内容をさらに深く理解したい方におすすめの一冊です。実践的な知識を身につけたい方は、ぜひチェックしてみてください!
おすすめコンテンツ
おすすめGitHub Actions2025/5/23GitHub Actionsワークフローが失敗する時の原因と解決法!初心者でも5分で修正できる実践ガイド
GitHub Actionsでワークフローが失敗して困っていませんか?よくあるエラーの原因と具体的な解決方法を、実際のコード例を交えて分かりやすく解説します。構文エラー、権限問題、依存関係のトラブルま...
続きを読む TanStack Query2025/6/2TanStack Query(React Query)完全ガイド!データフェッチングとキャッシュ戦略の実践的な使い方
TanStack Query(React Query)でReactアプリのデータフェッチングを効率化する方法を実例とともに解説します。キャッシュ戦略、エラーハンドリング、パフォーマンス最適化まで実践的...
続きを読む Node.js2025/5/20Node.jsアプリケーションのCORSエラー解決法:5分で実装できる完全ガイド
フロントエンドとバックエンドの連携で頻繁に遭遇するCORSエラーの原因と解決策を具体的なコード例とともに解説します。Node.js環境でのCORSポリシーの正しい設定方法から、開発環境と本番環境での違...
続きを読む TypeScript2025/6/2TypeScriptでGitHub Actionsカスタムアクション開発完全ガイド!CI/CDワークフローを効率化する実践的な作り方
TypeScriptを使ってGitHub Actionsのカスタムアクションを開発する方法を初心者でも理解できるよう詳しく解説します。実際のコード例とベストプラクティスで、あなたのCI/CDワークフロ...
続きを読む GitHub Copilot2025/5/29GitHub Copilotで開発効率を10倍にする実践的な使い方
GitHub Copilotを活用して開発効率を劇的に向上させる方法を解説します。インストールから基本的な使い方、高度な活用テクニックまで、実際のコード例を交えながら詳しく説明します。
続きを読む Vercel2025/5/24Vercelデプロイで失敗する時の原因と解決法!初心者でも5分で修正できる実践ガイド
Vercelデプロイ時によくあるエラーの原因と具体的な解決法を解説します。ビルドエラー、環境変数の設定ミス、ドメイン問題まで、実際のコード例付きで初心者でも簡単に修正できる方法をご紹介します。
続きを読む Docker2025/5/16Docker Composeで開発環境を簡単構築!初心者向け完全ガイド
Docker Composeの基本から実践的な使い方まで初心者にもわかりやすく解説。複数コンテナの管理や開発環境の効率化方法を具体的なサンプルとともに紹介します。
続きを読む Git2025/5/14Gitの脱初心者コマンド集!開発効率を上げる実践的な使い方
基本的なGitコマンドは理解したけど、もっと効率的に使いたい方へ。Gitの脱初心者コマンドを解説します。ステージングの便利な操作、コミット履歴の編集、トラブル対応まで、実務で使える実践的なGitの使い...
続きを読む