--- title: Consider Composables Instead of Renderless Components impact: MEDIUM impactDescription: Renderless slot components add overhead compared to composables for pure logic reuse type: best-practice tags: [vue3, slots, renderless-components, composables, performance, composition-api] --- # Consider Composables Instead of Renderless Components **Impact: MEDIUM** - Renderless components (components that only expose logic via scoped slots without rendering their own UI) were a popular pattern in Vue 2 for logic reuse. In Vue 3, Composition API composables are often more efficient and simpler for the same use case. ## Task Checklist - [ ] Evaluate if a composable can replace a renderless component - [ ] Use renderless components when slot-based composition is genuinely needed - [ ] Prefer composables for pure logic/state sharing - [ ] Consider component overhead vs function overhead **Renderless Component Pattern:** ```vue ``` ```vue
Mouse: {{ x }}, {{ y }}
``` **Composable Alternative (Recommended):** ```typescript // composables/useMouse.ts import { ref, onMounted, onUnmounted } from 'vue' export function useMouse() { const x = ref(0) const y = ref(0) function update(event: MouseEvent) { x.value = event.pageX y.value = event.pageY } onMounted(() => window.addEventListener('mousemove', update)) onUnmounted(() => window.removeEventListener('mousemove', update)) return { x, y } } ``` ```vue ``` ## When to Use Each Pattern | Pattern | Best For | |---------|----------| | **Composables** | Pure logic reuse, state management, side effects | | **Renderless Components** | When slot composition is needed, wrapper logic with flexible children | ### Use Composables When: - Sharing reactive state and methods - Encapsulating side effects (event listeners, timers) - No need for template slot composition - Maximum performance is needed ### Use Renderless Components When: - Need to provide context/data to arbitrary slot content - Building provider components (like context providers) - The slot composition pattern is genuinely useful - Building component libraries with maximum flexibility ## Real-World Examples **Composable is Better:** ```typescript // Data fetching export function useFetch(url: string) { const data = ref(null) const error = ref(null) const loading = ref(true) // ... fetch logic return { data, error, loading } } // Form validation export function useForm(initialValues) { const values = ref(initialValues) const errors = ref({}) const validate = () => { /* ... */ } return { values, errors, validate } } ``` **Renderless Component is Better:** ```vue ``` ## Performance Consideration Renderless components still: - Create a component instance - Go through the Vue component lifecycle - Have reactive overhead Composables are just functions: - No component instance overhead - Direct reactive primitives - Smaller bundle size ## Reference - [Vue.js Slots - Renderless Components](https://vuejs.org/guide/components/slots.html#renderless-components) - [Vue.js Composables](https://vuejs.org/guide/reusability/composables.html)