What Causes This Warning?
This warning occurs when you call app.unmount() on a Vue application instance that was never mounted, or was already unmounted previously.
The Problem
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// ❌ Unmounting before mounting
app.unmount() // Warning!
// ❌ Unmounting twice
app.mount('#app')
app.unmount()
app.unmount() // Warning!
The Fix
Mount Before Unmounting
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// ✅ Mount first
app.mount('#app')
// Later when needed
app.unmount()
Track Mount State
import { createApp } from 'vue'
import App from './App.vue'
let app = null
let isMounted = false
function mountApp() {
if (isMounted) return
app = createApp(App)
app.mount('#app')
isMounted = true
}
function unmountApp() {
if (!isMounted || !app) return
app.unmount()
app = null
isMounted = false
}
Common Scenarios
Conditional Mounting
// ❌ Might unmount when never mounted
function toggleApp(shouldMount) {
if (shouldMount) {
app.mount('#app')
} else {
app.unmount() // Error if never mounted!
}
}
// ✅ Track state properly
let mounted = false
function toggleApp(shouldMount) {
if (shouldMount && !mounted) {
app.mount('#app')
mounted = true
} else if (!shouldMount && mounted) {
app.unmount()
mounted = false
}
}
Modal/Dialog Apps
// ✅ Proper modal app lifecycle
class ModalManager {
constructor() {
this.app = null
this.container = null
}
show(component, props) {
// Create container
this.container = document.createElement('div')
document.body.appendChild(this.container)
// Create and mount app
this.app = createApp(component, props)
this.app.mount(this.container)
}
hide() {
if (this.app) {
this.app.unmount()
this.app = null
}
if (this.container) {
this.container.remove()
this.container = null
}
}
}
const modal = new ModalManager()
modal.show(MyModal, { title: 'Hello' })
modal.hide()
Hot Module Replacement
// vite HMR example
let app = createApp(App)
app.mount('#app')
if (import.meta.hot) {
import.meta.hot.accept('./App.vue', (newModule) => {
// ✅ Check before unmounting
if (app._container) {
app.unmount()
}
app = createApp(newModule.default)
app.mount('#app')
})
}
Multiple App Instances
const apps = new Map()
function createMiniApp(id, component) {
const container = document.getElementById(id)
if (!container) return
// Unmount existing if present
if (apps.has(id)) {
apps.get(id).unmount()
}
const app = createApp(component)
app.mount(container)
apps.set(id, app)
}
function destroyMiniApp(id) {
const app = apps.get(id)
if (app) {
app.unmount()
apps.delete(id)
}
}
function destroyAllApps() {
apps.forEach((app, id) => {
app.unmount()
})
apps.clear()
}
Cleanup on Navigation
// router.js
import { createRouter } from 'vue-router'
const dynamicApps = []
router.beforeEach((to, from) => {
// Clean up dynamic apps when navigating
dynamicApps.forEach(app => {
if (app._container) {
app.unmount()
}
})
dynamicApps.length = 0
})
export function registerDynamicApp(app) {
dynamicApps.push(app)
}
Using _container Check
// Vue sets _container when mounted
const app = createApp(App)
// Before unmounting, check if mounted
function safeUnmount(app) {
if (app._container) {
app.unmount()
return true
}
return false
}
// Usage
app.mount('#app')
safeUnmount(app) // Works
safeUnmount(app) // Returns false, no warning
Full Lifecycle Example
class VueAppManager {
constructor(component, containerId) {
this.component = component
this.containerId = containerId
this.app = null
}
mount(props = {}) {
if (this.app?._container) {
console.warn('App already mounted')
return this
}
const container = document.getElementById(this.containerId)
if (!container) {
console.error(`Container #${this.containerId} not found`)
return this
}
this.app = createApp(this.component, props)
this.app.mount(container)
return this
}
unmount() {
if (!this.app?._container) {
console.warn('App not mounted')
return this
}
this.app.unmount()
this.app = null
return this
}
isMounted() {
return !!this.app?._container
}
}
// Usage
const manager = new VueAppManager(App, 'app')
manager.mount({ prop: 'value' })
console.log(manager.isMounted()) // true
manager.unmount()
console.log(manager.isMounted()) // false
Quick Checklist
- Always mount before unmounting
- Don’t unmount the same app twice
- Track mount state for conditional mounting
- Use
app._containerto check if mounted - Clean up apps on navigation or component destroy
- Create wrapper class for complex app management