Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Vue 3 debugging reference for reactivity issues, computed errors, watcher bugs, async failures, and SSR hydration problems.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
reference/composition-api-not-functional-programming.md
1---2title: Composition API Uses Mutable Reactivity, Not Functional Programming3impact: MEDIUM4impactDescription: Misunderstanding the paradigm leads to incorrect state management patterns5type: gotcha6tags: [vue3, composition-api, reactivity, functional-programming, paradigm]7---89# Composition API Uses Mutable Reactivity, Not Functional Programming1011**Impact: MEDIUM** - Despite being function-based, the Composition API follows Vue's mutable, fine-grained reactivity paradigm—NOT functional programming principles. Treating it like a functional paradigm leads to incorrect patterns like unnecessary cloning, immutable-style updates, or avoiding mutation when mutation is the intended pattern.1213Vue's Composition API leverages imported functions to organize code, but the underlying model is based on mutable reactive state that Vue tracks and responds to. This is fundamentally different from functional programming with immutability (like Redux reducers).1415## Task Checklist1617- [ ] Mutate reactive state directly - don't create new objects for every update18- [ ] Don't apply immutability patterns unnecessarily (spreading, Object.assign for updates)19- [ ] Understand that `ref()` and `reactive()` enable mutable state tracking20- [ ] Use Vue's reactivity as intended: direct mutation with automatic tracking2122**Incorrect:**23```javascript24import { ref } from 'vue'2526const todos = ref([])2728// WRONG: Treating Vue like Redux/functional - unnecessary immutability29function addTodo(todo) {30// Creating a new array every time is wasteful in Vue31todos.value = [...todos.value, todo]32}3334function updateTodo(id, updates) {35// Unnecessary spread - Vue tracks mutations directly36todos.value = todos.value.map(t =>37t.id === id ? { ...t, ...updates } : t38)39}4041const user = ref({ name: 'John', age: 30 })4243// WRONG: Creating new object for simple update44function updateName(newName) {45user.value = { ...user.value, name: newName }46}47```4849**Correct:**50```javascript51import { ref, reactive } from 'vue'5253const todos = ref([])5455// CORRECT: Mutate directly - Vue tracks the change56function addTodo(todo) {57todos.value.push(todo) // Direct mutation is the Vue way58}5960function updateTodo(id, updates) {61const todo = todos.value.find(t => t.id === id)62if (todo) {63Object.assign(todo, updates) // Direct mutation64}65}6667const user = ref({ name: 'John', age: 30 })6869// CORRECT: Mutate the property directly70function updateName(newName) {71user.value.name = newName // Vue tracks this!72}7374// Or with reactive():75const state = reactive({ name: 'John', age: 30 })7677function updateNameReactive(newName) {78state.name = newName // Direct mutation, reactivity preserved79}80```8182## When Immutability Patterns Make Sense8384```javascript85// Immutability IS appropriate when:8687// 1. Replacing the entire state (e.g., from API response)88const users = ref([])89async function fetchUsers() {90users.value = await api.getUsers() // Complete replacement is fine91}9293// 2. When you need a snapshot for comparison94const previousState = { ...currentState } // For undo/redo9596// 3. When passing data to external libraries expecting immutable data97const chartData = computed(() => [...rawData.value]) // Copy for chart lib98```99100## The Vue Mental Model101102```javascript103// Vue's reactivity is like a spreadsheet:104// - Cell A1 contains a value (ref)105// - Cell B1 has a formula referencing A1 (computed)106// - Change A1, and B1 automatically updates107108const a1 = ref(10)109const b1 = computed(() => a1.value * 2)110111// You CHANGE A1 (mutate), you don't create a new A1112a1.value = 20 // b1 automatically becomes 40113114// This is fundamentally different from:115// state = reducer(state, action) // Functional/Redux pattern116```117118## Reference119- [Composition API FAQ](https://vuejs.org/guide/extras/composition-api-faq.html)120- [Reactivity Fundamentals](https://vuejs.org/guide/essentials/reactivity-fundamentals.html)121