Dalam pengembangan aplikasi modern, konsep sistem reactive dengan Proxy dan Observer semakin populer karena memberikan efisiensi dan kemudahan dalam mengelola perubahan data secara otomatis. Jika dulu kita harus memanggil fungsi render() setiap kali data berubah, kini JavaScript modern memungkinkan pembaruan tampilan yang lebih dinamis tanpa intervensi manual.
Prinsip reactive ini menjadi dasar dari berbagai framework seperti Vue.js, Svelte, dan Reactivity Core pada banyak library UI modern. Namun, menariknya, kita bisa membangun sistem serupa secara mandiri menggunakan fitur bawaan JavaScript seperti Proxy(), Reflect, dan pola Observer Pattern. Artikel ini akan membahas langkah demi langkah cara menciptakan sistem reactive sederhana, bagaimana state otomatis memicu pembaruan UI, dan bagaimana cara mengembangkannya menjadi sistem yang lebih kompleks tanpa menggunakan framework besar.
Konsep Dasar Sistem Reactive
Sistem reactive adalah pola pemrograman di mana perubahan pada data secara otomatis mengubah bagian antarmuka yang bergantung pada data tersebut. Artinya, kita tidak perlu menulis ulang logika render setiap kali nilai berubah — sistem akan melakukannya secara otomatis.
Untuk mencapainya, dibutuhkan dua hal penting:
-
Observer Pattern, yang memantau perubahan data dan mengeksekusi efek tertentu ketika terjadi perubahan.
-
Proxy(), fitur JavaScript modern yang memungkinkan kita “mengawasi” setiap operasi pada objek seperti
get,set, ataudelete.
Gabungan keduanya menghasilkan mekanisme reaktif yang efisien dan mudah dikelola.
Membuat Sistem Reactive dengan Proxy()
Mari mulai dari contoh sederhana.
const data = {
message: "Halo Dunia!"
};
const handler = {
set(target, key, value) {
target[key] = value;
console.log(`Data berubah: ${key} -> ${value}`);
updateUI();
return true;
}
};
const state = new Proxy(data, handler);
function updateUI() {
document.getElementById('app').textContent = state.message;
}
Dengan kode di atas, setiap kali kita mengubah state.message, fungsi updateUI() akan otomatis dijalankan tanpa perlu dipanggil manual.
Contoh:
state.message = "Halo JavaScript Modern!";
Akan langsung memperbarui elemen dengan id app di halaman.
Menambahkan Observer Pattern
Agar lebih fleksibel, kita bisa menambahkan sistem observer agar beberapa fungsi dapat “mendengarkan” perubahan data.
const observers = new Set();
function observe(fn) {
observers.add(fn);
}
function notify() {
observers.forEach(fn => fn());
}
const reactiveData = new Proxy(data, {
set(target, key, value) {
target[key] = value;
notify();
return true;
}
});
Kemudian, kita bisa mendaftarkan fungsi yang akan dijalankan setiap kali data berubah:
observe(() => {
document.getElementById("app").textContent = reactiveData.message;
});
Setiap kali reactiveData.message diperbarui, semua observer function akan otomatis dijalankan.
Tanpa Re-render Manual
Dengan kombinasi Proxy() dan Observer Pattern, kita tidak lagi memanggil updateUI() secara manual. Berikut contoh implementasi penuh:
<div id="app"></div>
<input id="input" type="text" placeholder="Ketik pesan...">
<script>
const data = { message: "Selamat datang!" };
const observers = new Set();
function observe(fn) {
observers.add(fn);
}
function notify() {
observers.forEach(fn => fn());
}
const state = new Proxy(data, {
set(target, key, value) {
target[key] = value;
notify();
return true;
}
});
observe(() => {
document.getElementById("app").textContent = state.message;
});
document.getElementById("input").addEventListener("input", e => {
state.message = e.target.value;
});
</script>
Ketika pengguna mengetik di input, teks pada elemen #app akan berubah secara real-time — tanpa re-render manual.
Keuntungan Pendekatan Reactive
-
Efisiensi Tinggi:
Perubahan data langsung berdampak ke tampilan tanpa loop berulang atau render ulang penuh. -
Kode Lebih Bersih:
Tidak perlu lagi memanggil fungsi pembaruan di setiap aksi. -
Mudah Dikembangkan:
Dapat diperluas menjadi mini-framework reactive sederhana untuk kebutuhan aplikasi SPA atau dashboard ringan.
Mengembangkan Sistem Reactive Lebih Lanjut
Setelah memiliki dasar sistem reactive, Anda bisa mengembangkannya menjadi lebih canggih, misalnya:
-
Menambahkan Deep Proxy, agar perubahan pada nested object juga terdeteksi.
-
Menyediakan Computed Property, seperti pada Vue.js.
-
Menggunakan Dependency Tracking agar hanya bagian tertentu dari UI yang diperbarui.
-
Menambahkan Batch Update, supaya perubahan besar tetap efisien.
Contoh pengembangan kecil — menambahkan dukungan untuk properti bersarang:
function createReactive(obj) {
const observers = new Set();
const proxy = new Proxy(obj, {
get(target, key) {
const value = target[key];
return typeof value === 'object' && value !== null ? createReactive(value) : value;
},
set(target, key, value) {
target[key] = value;
observers.forEach(fn => fn());
return true;
}
});
proxy.observe = fn => observers.add(fn);
return proxy;
}
Dengan fungsi ini, Anda bisa membuat data reaktif yang lebih kompleks seperti:
const state = createReactive({ user: { name: "Arvian" } });
state.observe(() => console.log("Data berubah!"));
state.user.name = "Ticiamiz"; // otomatis terdeteksi
Kesimpulan
Membuat sistem reactive dengan Proxy dan Observer memungkinkan pengembang membangun aplikasi JavaScript modern yang efisien dan mudah dikelola tanpa perlu framework berat. Dengan hanya beberapa baris kode, kita dapat menghubungkan data dengan tampilan secara otomatis, menciptakan pengalaman pengguna yang dinamis dan responsif.
Pendekatan ini juga menjadi dasar bagi sistem reaktif di framework besar seperti Vue dan Svelte — membuktikan bahwa JavaScript murni pun mampu menghadirkan performa dan fleksibilitas tinggi dalam pengembangan aplikasi web modern.