Fix: Component Missing Template or Render Function in Vue.js

Error message:
Component is missing template or render function:
Components 2025-01-25

What Causes This Warning?

This warning appears when Vue tries to render a component that has no template, render function, or <template> block. Every Vue component needs a way to define its visual output.

The Problem

// ❌ Component with no template or render
export default {
  name: 'MyComponent',
  setup() {
    const count = ref(0)
    return { count }
  }
  // Missing template!
}
<!-- ❌ SFC with empty or missing template -->
<script setup>
const message = ref('Hello')
</script>

<!-- No <template> block! -->

The Fix

Add a Template Block (SFC)

<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>

<!-- ✅ Add template block -->
<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="count++">Increment</button>
  </div>
</template>

Use Template Option

// ✅ Add template option
export default {
  template: `
    <div>
      <p>Count: {{ count }}</p>
      <button @click="count++">Increment</button>
    </div>
  `,
  setup() {
    const count = ref(0)
    return { count }
  }
}

Use Render Function

import { h, ref } from 'vue'

// ✅ Use render function
export default {
  setup() {
    const count = ref(0)

    return () => h('div', [
      h('p', `Count: ${count.value}`),
      h('button', { onClick: () => count.value++ }, 'Increment')
    ])
  }
}

Use JSX (with plugin)

// ✅ Use JSX (requires @vitejs/plugin-vue-jsx)
export default {
  setup() {
    const count = ref(0)

    return () => (
      <div>
        <p>Count: {count.value}</p>
        <button onClick={() => count.value++}>Increment</button>
      </div>
    )
  }
}

Common Scenarios

Wrong File Extension

// ❌ .js file trying to use template syntax
// MyComponent.js
export default {
  template: '<div>{{ message }}</div>',
  data() {
    return { message: 'Hello' }
  }
}
// This works but requires runtime compiler!

// ✅ Use .vue file for SFC syntax
// MyComponent.vue

Async Component Loading Issue

// ❌ Async import returning wrong value
const MyComponent = defineAsyncComponent(() =>
  import('./MyComponent.js') // Might not export component correctly
)

// ✅ Ensure correct export
const MyComponent = defineAsyncComponent(() =>
  import('./MyComponent.vue')
)

Functional Components

// ❌ Functional component returning nothing
const Badge = (props) => {
  // No return!
}

// ✅ Functional component with return
const Badge = (props) => {
  return h('span', { class: 'badge' }, props.text)
}

Renderless Components

// ✅ Renderless component (renders slot content)
export default {
  setup(props, { slots }) {
    const data = useSomeLogic()

    // Return slot content with data
    return () => slots.default?.({ data })
  }
}

// Usage
<RenderlessComponent v-slot="{ data }">
  <div>{{ data }}</div>
</RenderlessComponent>

Build Configuration

If using template strings, ensure the Vue compiler is included:

// vite.config.js
import vue from '@vitejs/plugin-vue'

export default {
  plugins: [vue()],
  resolve: {
    alias: {
      // Use full build with compiler (if needed)
      'vue': 'vue/dist/vue.esm-bundler.js'
    }
  }
}

Quick Checklist

  • SFC files need a <template> block
  • JS components need template option or render function
  • Check file extension (.vue for SFCs)
  • Ensure proper component export
  • For renderless components, return slot content
  • Use runtime compiler if using template strings