Episode ini mendalami manajemen state reaktif di Vue 3: ref dan reactive, computed properties, watchers, lifecycle hooks, serta perbandingan Composition API dan Options API, diakhiri dengan pembuatan custom composables untuk logika yang dapat dipakai ulang.

Di episode 4 kalian sudah merender data dan merespons event. Sekarang waktunya memahami otak aplikasi: state reaktif. Seberapa baik kalian mengelola state menentukan seberapa mudah aplikasi dipelihara — dan Composition API di Vue 3 dirancang agar state dan logika bisa dikelompokkan dengan rapi.
Episode 5 membedah ref dan reactive, computed untuk nilai turunan, watchers untuk reaksi terhadap perubahan, dan lifecycle hooks. Lalu kita bandingkan Composition API dan Options API, dan ditutup dengan custom composables — teknik yang akan kalian pakai di hampir semua episode koding berikutnya.
ref membungkus nilai apa pun menjadi reaktif. Akses nilai lewat properti .value:
import { ref } from "vue";
const jumlah = ref(0);
jumlah.value = 5;Saat jumlah.value berubah, setiap bagian template yang bergantung padanya ikut diperbarui. Ref bekerja untuk primitif maupun object, dan selalu aman di-destructure karena nilainya diakses lewat .value.
reactive membungkus object agar propertinya langsung reaktif:
import { reactive } from "vue";
const user = reactive({
nama: "Arman",
skill: ["Vue", "Node.js"],
});
user.nama = "Budi";
user.skill.push("TypeScript");Modifikasi user.nama = "Budi" dan user.skill.push("TypeScript") langsung tercatat oleh sistem reaktivitas, termasuk perubahan di dalam array. Gunakan reactive untuk object dengan banyak field, dan ref untuk nilai tunggal atau saat dibutuhkan kemampuan di-unwrap di template.
computed membuat nilai turunan yang di-cache dan hanya dihitung ulang saat dependensinya berubah:
import { ref, computed } from "vue";
const harga = ref(200000);
const diskon = ref(0.1);
const total = computed(() => harga.value * (1 - diskon.value));total otomatis diperbarui saat harga atau diskon berubah, tanpa perhitungan ulang yang sia-sia. Karena di-cache, computed lebih efisien dibanding memanggil fungsi biasa di template.
watch bereaksi terhadap satu perubahan spesifik; watchEffect melacak semua dependensi yang dibaca dan langsung berjalan:
import { ref, watch, watchEffect } from "vue";
const query = ref("");
watch(query, (nilaiBaru) => {
console.log("query berubah:", nilaiBaru);
});
watchEffect(() => {
console.log("query saat ini:", query.value);
});Perbedaan kuncinya: watch(query, ...) hanya memicu saat query berubah, sedangkan watchEffect(...) langsung berjalan sekali di awal dan setiap kali dependensinya berubah.
Lifecycle hooks dieksekusi pada momen tertentu siklus hidup komponen:
import { onMounted, onUnmounted, watchEffect } from "vue";
onMounted(() => {
console.log("komponen siap");
});
onUnmounted(() => {
console.log("komponen dilepas");
});onMounted dipakai untuk inisialisasi seperti pemanggilan API, dan onUnmounted untuk pembersihan seperti menghapus interval atau listener.
Options API menyusun logika dalam option data, computed, dan methods:
<script>
export default {
data() {
return { jumlah: 0 };
},
methods: {
tambah() {
this.jumlah = this.jumlah + 1;
},
},
};
</script>Composition API menyusun semuanya dalam fungsi setup atau <script setup>:
<script setup>
import { ref } from "vue";
const jumlah = ref(0);
function tambah() {
jumlah.value = jumlah.value + 1;
}
</script>Composition API lebih fleksibel untuk logika yang saling terkait karena kalian bisa mengelompokkan code sesuai fungsi, bukan menurut tipe. Options API lebih mudah dibaca untuk komponen kecil dan masih didukung penuh. Keduanya sah; series ini memakai Composition API karena lebih cocok untuk aplikasi besar dan composables.
Composable adalah fungsi yang memakai Composition API dan mengembalikan state yang bisa dipakai ulang. Contoh paling klasik: counter dan timer:
import { ref, computed } from "vue";
export function useCounter(awal = 0) {
const jumlah = ref(awal);
const ganda = computed(() => jumlah.value * 2);
function tambah() {
jumlah.value = jumlah.value + 1;
}
return { jumlah, ganda, tambah };
}Simpan sebagai src/composables/useCounter.js. Konvensi penamaan composables selalu diawali use, sehingga kalian bisa mengenalinya sekilas.
useCounter(10) membuat instance counter baru dengan nilai awal 10, dan setiap komponen pemakainya mendapat state terpisah.
Episode 5 mengajarkan kalian mengelola state dengan benar: ref dan reactive untuk state dasar, computed untuk nilai turunan yang efisien, watchers untuk reaksi terhadap perubahan, lifecycle hooks untuk inisialisasi dan pembersihan, serta composables untuk logika yang bisa dipakai ulang.
Inti yang harus dibawa pulang:
ref untuk nilai tunggal, reactive untuk object.computed di-cache dan hanya dihitung saat dependensi berubah.watch memantau perubahan spesifik; watchEffect melacak semuanya.onMounted untuk inisialisasi, onUnmounted untuk pembersihan.use membungkus logika yang bisa dipakai ulang.Di episode 6 selanjutnya kita membahas component communication — props dan custom events dengan defineEmits, provide/inject untuk dependency injection, slots dan scoped slots, serta pattern komponen yang bisa dipakai ulang untuk UI yang konsisten.