Pernah nggak kamu nulis ulang logika loading state dan error handler di tiga komponen berbeda, terus baru sadar semuanya identik? Itu bukan tanda kamu rajin — itu tanda kamu butuh composables Vue 3. Fitur inti Composition API ini memungkinkan kamu mengemas reusable logic Vue dalam satu fungsi yang bisa dipanggil dari mana saja, persis seperti custom hook di React, tapi dengan cita rasa Vue yang bersih dan intuitif.
Di artikel ke-13 seri Vue from Zero to Zorro ini, kita bakal bedah tuntas: apa itu composables, kenapa kamu harus pakai, dan bagaimana cara membuatnya dari nol sampai siap produksi.
📌 Definisi Kunci
Composable adalah fungsi JavaScript biasa yang menggunakan Composition API Vue 3 (seperti ref, computed, watch) untuk merangkum logika stateful yang bisa dipakai ulang lintas komponen. Namanya selalu diawali use — misalnya useFetch, useCounter, useLocalStorage.
🧰 Apa Itu Composables Vue 3 dan Kenapa Kamu Butuhnya?
Bayangkan kamu punya resep bumbu rahasia yang enak banget. Daripada kamu tulis ulang resep itu setiap kali mau masak, bukankah lebih praktis kalau resepnya disimpan di satu kartu dan tinggal dipakai kapan saja? Itulah filosofi composables — satu tempat, bisa dipakai di mana-mana.
Sebelum Vue 3 hadir, kita pakai mixins untuk berbagi logika. Tapi mixins punya masalah: sumber data tidak jelas, bisa bentrok nama, dan susah di-debug. Composables hadir sebagai solusi yang lebih bersih: eksplisit, type-safe, dan mudah di-test.
Fakta Menarik
VueUse — library composables paling populer di ekosistem Vue — punya lebih dari 200+ composables siap pakai untuk segala kebutuhan: dari deteksi gerak mouse, dark mode, hingga akselerometer perangkat. Kamu bisa langsung install dan pakai tanpa nulis dari nol!
🛠️ Cara Membuat Composables Vue 3 dari Nol — Step by Step
Oke, teori cukup. Sekarang kita langsung praktek bikin composable pertama kamu. Kita mulai dari kasus nyata: composable counter, lalu naik level ke composable fetch data.
Buat File Composable
Buat folder composables/ di dalam src/, lalu buat file dengan awalan use. Konvensi ini penting agar tim kamu langsung tahu ini composable, bukan komponen biasa.
📁 src/composables/useCounter.js
import { ref, computed } from 'vue' export function useCounter(initialValue = 0) { const count = ref(initialValue) const doubled = computed(() => count.value * 2) function increment() { count.value++ } function decrement() { count.value-- } function reset() { count.value = initialValue } return { count, doubled, increment, decrement, reset } }
Gunakan di Komponen
Panggil composable di dalam setup() atau langsung di blok <script setup>. Gunakan destructuring untuk mengambil hanya yang kamu butuhkan.
📄 src/components/CounterA.vue
<script setup> import { useCounter } from '../composables/useCounter' // Ambil yang kamu butuhkan saja! const { count, doubled, increment, reset } = useCounter(10) </script> <template> <div> <p>Count: {{ count }}</p> <p>Doubled: {{ doubled }}</p> <button @click="increment">+</button> <button @click="reset">Reset</button> </div> </template>
Tips Naming Convention
Selalu awali nama composable dengan use (useCounter, useFetch, useAuth). Ini bukan sekedar gaya — ini sinyal resmi ke Vue DevTools dan linter bahwa fungsi ini menggunakan Composition API dan harus dipanggil di dalam setup().
Composable untuk Fetch Data (Level Up!)
Ini contoh yang lebih relevan untuk proyek nyata — composable useFetch yang bisa dipakai di komponen mana pun tanpa nulis ulang logika loading/error.
📁 src/composables/useFetch.js
import { ref, watchEffect } from 'vue' export function useFetch(url) { const data = ref(null) const error = ref(null) const loading = ref(false) watchEffect(async () => { loading.value = true error.value = null try { const res = await fetch(url.value ?? url) data.value = await res.json() } catch (e) { error.value = e.message } finally { loading.value = false } }) return { data, error, loading } }
⚡ Reusable Logic Vue: Composable dalam Aksi di Banyak Komponen
Kekuatan sejati reusable logic Vue terlihat ketika kamu pakai satu composable di puluhan komponen tanpa duplikasi kode. Setiap komponen mendapat instance state-nya sendiri — tidak ada state yang bocor ke komponen lain.
📄 ProductList.vue — pakai useFetch yang sama
<script setup> import { useFetch } from '../composables/useFetch' const { data: products, loading, error } = useFetch('https://fakestoreapi.com/products') </script> <template> <div> <p v-if="loading">Loading produk...</p> <p v-else-if="error">Error: {{ error }}</p> <ul v-else> <li v-for="p in products" :key="p.id"> {{ p.title }} </li> </ul> </div> </template>
Insight Penting
Setiap kali kamu memanggil composable, Vue membuat instance reaktif yang terpisah. Jadi useFetch di ProductList dan useFetch di UserProfile punya state data, loading, error masing-masing — tidak ada yang overlap!
🚀 Composables Lanjutan: Lifecycle, Watch, dan Best Practice
Composables bukan hanya untuk state sederhana. Kamu juga bisa menyematkan lifecycle hooks dan watchers di dalamnya — dan semuanya akan otomatis bersih saat komponen di-unmount.
📁 src/composables/useMousePosition.js
import { ref, onMounted, onUnmounted } from 'vue' export function useMousePosition() { const x = ref(0) const y = ref(0) function update(e) { x.value = e.clientX y.value = e.clientY } onMounted(() => window.addEventListener('mousemove', update)) onUnmounted(() => window.removeEventListener('mousemove', update)) return { x, y } }
Perhatian
Composable wajib dipanggil di dalam setup() atau di level atas <script setup>. Jangan panggil di dalam kondisional (if), loop (for), atau callback async — ini akan merusak urutan hooks dan menyebabkan bug yang susah dideteksi!
🔍 Anatomi Composable yang Ideal
📥
Input
Parameter atau ref yang bisa reaktif. Terima nilai biasa atau MaybeRef untuk fleksibilitas.
⚙️
Logic
State reaktif, computed, watchers, lifecycle hooks — semuanya dirangkum di sini.
📤
Output
Return object berisi ref reaktif dan fungsi. Selalu return object (bukan array) agar mudah di-destructure dengan alias.
Tips Pro: Jangan Reinvent the Wheel
Sebelum bikin composable sendiri, cek dulu VueUse di vueuse.org. Library ini punya 200+ composables siap pakai — mulai dari useLocalStorage, useDark, useIntersectionObserver, hingga useWebSocket. Install sekali, hemat berjam-jam coding!
📚
Ini Bagian dari Seri Lengkap
Artikel ini adalah bagian ke-13 dari 16 artikel dalam seri Vue from Zero to Zorro. Dari dasar sampai mahir — semuanya tersedia di satu tempat.
🗂️ Lihat Semua 16 Artikel →🎯 Kesimpulan
Composables Vue 3 adalah jawaban elegan untuk masalah duplikasi kode yang selama ini menghantui developer frontend. Dibandingkan mixins, composables jauh lebih eksplisit, type-safe, dan mudah diuji.
- ✅ Awali nama dengan
use— ini konvensi resmi Vue - ✅ Return selalu berupa object agar mudah di-destructure dengan alias
- ✅ Lifecycle hooks di dalam composable auto-cleanup saat komponen unmount
- ✅ Gunakan reusable logic Vue via VueUse sebelum bikin dari nol
- ✅ Panggil composable hanya di dalam
setup()— jangan di dalam kondisional
Gimana? Udah mulai kebayang kan betapa poweful-nya composables? Yuk share pengalamanmu di komentar — composable apa yang pertama kali kamu buat? Dan kalau artikel ini bermanfaat, jangan lupa share ke teman-teman yang lagi belajar Vue! 🚀
Navigasi Seri
← Artikel Sebelumnya
Fetch Data dari API — Koneksi Vue 3 ke Backend dengan Axios dan Tampilkan Data Real di UI
→ Baca Artikel Sebelumnya
No comments:
Post a Comment