Fix: useModel Called Without Active Instance in Vue.js

Error message:
useModel() called without active instance.
Composition API 2025-01-25

What Causes This Error?

This error occurs when useModel() is called outside of a component’s setup() function or after the synchronous setup phase has completed. Like other Composition API functions, useModel() requires an active component instance.

The Problem

import { useModel } from 'vue'

// ❌ Called outside setup
const model = useModel() // Error!

export default {
  setup() {
    // ...
  }
}
export default {
  async setup() {
    await fetchData()

    // ❌ Called after await
    const model = useModel() // Error!
  }
}

The Fix

<script setup>
// ✅ defineModel works in script setup
const model = defineModel()
const count = defineModel('count')
</script>

<template>
  <input v-model="model" />
</template>

Call Before Await

export default {
  async setup(props) {
    // ✅ Create model before await
    const modelValue = useModel(props, 'modelValue')

    await fetchData()

    return { modelValue }
  }
}

Common Scenarios

In Composables

// ❌ Composable might be called outside setup
export function useFormModel() {
  const model = useModel() // Might fail!
  return model
}

// ✅ Accept model from outside
export function useFormModel(modelRef) {
  // Work with provided model
  return {
    reset: () => modelRef.value = ''
  }
}

// Usage in component
<script setup>
const model = defineModel()
const { reset } = useFormModel(model)
</script>

With Async Operations

<script setup>
// ✅ Define model first (synchronous)
const value = defineModel()

// Then do async operations
onMounted(async () => {
  const data = await fetchData()
  value.value = data.defaultValue
})
</script>

Migration from useModel to defineModel

<!-- Old approach -->
<script>
import { useModel } from 'vue'

export default {
  props: ['modelValue'],
  emits: ['update:modelValue'],
  setup(props) {
    const model = useModel(props, 'modelValue')
    return { model }
  }
}
</script>

<!-- New approach (Vue 3.4+) -->
<script setup>
const model = defineModel()
</script>

defineModel Examples

<script setup>
// Basic v-model
const value = defineModel()

// Named v-model
const title = defineModel('title')

// With options
const count = defineModel('count', {
  type: Number,
  default: 0,
  required: true
})

// TypeScript
const name = defineModel<string>('name', {
  default: ''
})
</script>

Quick Checklist

  • Use defineModel() in <script setup> (preferred)
  • Call useModel() synchronously in setup
  • Call before any await statements
  • Don’t call in callbacks, timeouts, or event handlers
  • Composables should accept model refs as parameters