Membangun Reactive Component Library Sederhana dengan JavaScript Vanilla

By | 19 October 2025

Di era modern JavaScript, framework seperti React, Vue, atau Svelte banyak digunakan untuk membangun antarmuka yang reaktif dan modular. Namun, tahukah kamu bahwa sebenarnya semua prinsip dasarnya bisa diterapkan hanya dengan JavaScript murni (vanilla JS)?

Artikel ini akan membahas bagaimana cara membuat Reactive Component JavaScript sederhana — yaitu sistem komponen yang bisa mengelola state, merender tampilan otomatis saat data berubah, dan digunakan kembali di berbagai bagian aplikasi.
Dengan memahami dasar ini, kamu tidak hanya belajar membuat sistem sendiri, tetapi juga akan lebih memahami bagaimana framework besar bekerja di balik layar.

Apa Itu Reactive Component?

Reactive Component adalah unit kode yang:

  • Memiliki state (data internal),

  • Dapat merender tampilan berdasarkan state tersebut, dan

  • Secara otomatis memperbarui tampilan jika state berubah.

Misalnya, sebuah tombol “Like” yang menampilkan jumlah suka, dan bertambah setiap kali diklik. Dengan pendekatan reaktif, komponen akan langsung memperbarui tampilannya tanpa harus menulis ulang seluruh halaman.

Membuat Fungsi Dasar createComponent()

Mari kita mulai dengan membuat fungsi utama yang akan menjadi fondasi sistem komponen kita.

function createComponent(rootId, initialState, template) {
  const root = document.getElementById(rootId);

  const state = new Proxy(initialState, {
    set(target, prop, value) {
      target[prop] = value;
      render();
      return true;
    },
  });

  function render() {
    root.innerHTML = template(state);
  }

  render();
  return state;
}

Penjelasan:

  • Proxy digunakan untuk memantau perubahan data.

  • template adalah fungsi yang mengembalikan HTML berdasarkan data.

  • Saat state berubah, fungsi render() otomatis dijalankan untuk memperbarui UI.

Contoh: Komponen Counter

Mari kita uji fungsi di atas dengan membuat komponen penghitung sederhana.

const counter = createComponent("app", { count: 0 }, (state) => `
  <h2>Counter: ${state.count}</h2>
  <button onclick="counter.count++">Tambah</button>
  <button onclick="counter.count--">Kurangi</button>
`);
<div id="app"></div>

Sekarang kamu punya sistem yang otomatis memperbarui UI setiap kali state berubah! Saat kamu klik tombol “Tambah” atau “Kurangi”, tampilan Counter langsung berubah — tanpa perlu addEventListener manual.

Membuat Banyak Komponen Sekaligus

Kita bisa menggunakan fungsi createComponent() untuk membuat beberapa komponen berbeda dalam satu halaman:

const likes = createComponent("likeBtn", { likes: 0 }, (state) => `
  <button onclick="likes.likes++">❤️ ${state.likes} Likes</button>
`);

const cart = createComponent("cartInfo", { items: 3 }, (state) => `
  <p>Keranjang kamu memiliki ${state.items} item.</p>
  <button onclick="cart.items++">Tambah Item</button>
`);
<div id="likeBtn"></div>
<div id="cartInfo"></div>

Setiap komponen memiliki state-nya sendiri dan render otomatis yang terpisah. Artinya, mereka benar-benar berdiri sendiri (isolated component), seperti halnya di framework React atau Vue.

Menambahkan Lifecycle Hooks (onMount dan onUpdate)

Agar lebih fleksibel, kita bisa menambahkan lifecycle hook sederhana seperti onMount() dan onUpdate() untuk menjalankan logika tertentu.

function createComponent(rootId, initialState, template, hooks = {}) {
  const root = document.getElementById(rootId);

  const state = new Proxy(initialState, {
    set(target, prop, value) {
      target[prop] = value;
      render();
      hooks.onUpdate && hooks.onUpdate(state);
      return true;
    },
  });

  function render() {
    root.innerHTML = template(state);
  }

  render();
  hooks.onMount && hooks.onMount(state);

  return state;
}

// Contoh penggunaan
const counter = createComponent(
  "app",
  { count: 0 },
  (state) => `<h3>${state.count}</h3><button onclick="counter.count++">+1</button>`,
  {
    onMount: () => console.log("Komponen dimuat!"),
    onUpdate: (state) => console.log("Nilai baru:", state.count),
  }
);

Sekarang setiap kali komponen dimuat atau di-update, fungsi hook akan dijalankan. Ini meniru cara kerja lifecycle event di framework modern seperti Vue (mounted, updated).

Pengembangan Lanjutan: Komponen Bersarang (Nested Component)

Sistem ini bisa dikembangkan agar mendukung komponen di dalam komponen. Misalnya, komponen TodoApp yang berisi daftar TodoItem.

function TodoItem(task) {
  return `<li>${task}</li>`;
}

const todos = createComponent("todoList", { items: ["Belajar JS", "Ngopi"] }, (state) => `
  <ul>
    ${state.items.map(TodoItem).join("")}
  </ul>
  <input id="newTask" placeholder="Tambah tugas..." />
  <button onclick="addTodo()">Tambah</button>
`);

function addTodo() {
  const input = document.getElementById("newTask");
  todos.items.push(input.value);
  todos.items = [...todos.items]; // trigger re-render
  input.value = "";
}
<div id="todoList"></div>

Setiap kali pengguna menambah tugas, daftar otomatis ter-render ulang tanpa reload.

Arah Pengembangan ke Depan

Dari sistem ini, kamu bisa mengembangkannya lebih lanjut menjadi mini framework dengan fitur-fitur seperti:

  • Routing (navigasi halaman)

  • Global state management

  • Reusable UI components (Card, Modal, Button)

  • Event bus atau store global

  • Data binding otomatis ke form input

Dengan beberapa langkah tambahan, kamu bisa membangun library seperti mini “React” versi kamu sendiri.

Kesimpulan

Membangun Reactive Component JavaScript dengan vanilla JS memberikan pemahaman mendalam tentang bagaimana framework modern bekerja. Dengan memanfaatkan Proxy, template, dan sedikit struktur modular, kita bisa menciptakan sistem komponen yang efisien, ringan, dan mudah dikembangkan tanpa ketergantungan pada library eksternal.

Belajar konsep ini akan membantu kamu memahami filosofi dasar di balik React, Vue, atau Svelte — sekaligus memberi kebebasan penuh dalam membangun framework versi kamu sendiri.