In Vue, component data must be a function so each instance gets its own state object. If it were a shared object, multiple instances would mutate the same reference and leak state between components. This avoids shared state bugs and makes components safer to reuse and test.
Why must data be a function in Vue components, and what breaks if it isn’t?
Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.
Core ideadata() must be a function in reusable component definitions so Vue can create a new state object per component instance. If you use a plain object, every instance points to the same object reference (shared state).
data option | What Vue needs | What happens in practice |
|---|---|---|
| A factory that returns a new object per instance | Each component instance has isolated state |
| A single object | All instances share the same state (cross-instance leaks) |
What breaks if data is an object?
Nothing “crashes” immediately—Vue can still make it reactive—but your component stops being instance-safe. The bugs show up as state leaking between instances.
<!-- WRONG: shared state across instances -->
<script>
const Counter = {
template: `
<button @click="count++">Count: {{ count }}</button>
`,
data: { count: 0 } // ❌ shared reference
};
export default {
components: { Counter }
};
</script>
<template>
<Counter />
<Counter />
</template>
<!-- Click one button -> both counters update because they share the same 'count'. -->
<!-- CORRECT: per-instance state -->
<script>
const Counter = {
template: `
<button @click="count++">Count: {{ count }}</button>
`,
data() {
return { count: 0 }; // ✅ new object per instance
}
};
export default {
components: { Counter }
};
</script>
<template>
<Counter />
<Counter />
</template>
Scenario | Symptom | Why it happens |
|---|---|---|
Rendering the same component multiple times | Changing state in one instance changes the others | All instances reference the same object |
Lists ( | Items “share” state unexpectedly (especially with filtering/sorting) | Instances are supposed to be isolated; shared data violates that |
SSR (Nuxt / server rendering) | Request-to-request state leakage between users | Server process reuses the same module/object across requests |
Rule of thumb
• If you want instance state (almost always): use data().
• If you want intentionally shared state: don’t “accidentally” share via data: {}—use a store (Pinia) or a clearly named shared module/composable.
Practical scenario
Rendering a list of card components, each needs isolated local state for toggles and counters.
Common pitfalls
- Using a shared object for data and leaking state between instances.
- Mutating data outside the component and causing side effects.
- Assuming reactivity works the same for shared references.
Returning a function is slightly more boilerplate but safer. Test two instances to ensure state stays isolated.
Vue requires data() in component definitions because components are instantiated multiple times. A function returns a fresh object per instance. If data is a plain object, state becomes shared, causing cross-instance bugs and (in SSR) even cross-user data leaks.