Komunikasi Antar Komponen React dengan Custom Event


Pernahkah anda mengalami masalah menghubungkan dua atau lebih komponen React yang secara kode letaknya jauh? Malas membuat state management di tingkat yang sangat tinggi hanya untuk kontrol buka-tutup sesuatu? Tidak mau ribet memasang library eksternal untuk mengatur state tersebut? Jangan khawatir, ada solusi bawaan dari platform web untuk hal tersebut.

Contoh Kasus Imajiner

Bayangkan kita memiliki sebuah toko online berbasis React yang di setiap halamannya terdapat sebuah header dengan dropdown untuk mengganti kurs mata uang. Komponen header ini menjadi sebuah template yang akan diaplikasikan di semua halaman.

Tampilan layout header

Contoh layout header

Komponen header ini berdiri bebas dan tidak terikat oleh isi halaman. Apapun isi halamannya, header tidak punya konteks mengenai halaman tersebut.

Pada suatu hari, muncullah sebuah permintaan fitur.

Di halaman pembayaran, apakah bisa kita munculkan sebuah tombol yang ketika diklik akan membuka dropdown yang ada di header untuk ganti kurs?

Gambaran fitur

Contoh simulasi fitur yang diinginkan

Tentu pastinya secara teknis hal ini memungkinkan. Yang jadi masalah adalah bagaimana mencapai ini tanpa mengubah banyak hal.

Ada beberapa cara yang mungkin terpikirkan:

  1. Memasang state dan fungsi untuk membuka-tutup dropdown. Solusi yang simpel. Dapat dicapai dengan React Context tapi kita harus membuat sebuah fungsi dan logika yang terletak di level yang setara atau di atas template halaman.
  2. Menggunakan library eksternal untuk memengatur state. Ada banyak alternatif seperti redux, zustand, jotai dan lain sebagainya. Ini adalah solusi yang cukup overkill apabila kita tidak memakai itu sebelumnya dan harus menambahkan hal tersebut sebagai hal baru.

Tidak ada yang salah dari dua solusi di atas, tapi dalam beberapa kondisi tidak semudah itu untuk memasang state di level yang sangat tinggi dan mungkin tidak sebebas itu juga untuk menambahkan library karena ada batasan tertentu. Salah satu solusinya adalah dengan menggunakan fitur bawaan web: Custom Event.

Custom Event

Pada dasarnya interaksi di browser didasari oleh berbagai event yang dikirimkan dan yang ditangkap. Nama-nama event pun biasanya sudah terdefinisi dan sering kita gunakan baik secara langsung maupun tidak. Event yang sering kita gunakan misalnya adalah:

  • Ketika ada sebuah elemen yang diklik - onClick, “click”
  • Ketika menekan sebuah tombol pada keyboard - onKeyPress, “keypress”
  • Ketika laman web selesai dimuat - onLoad, “load”
  • dan lain sebagainya

Semua event yang biasa kita gunakan sudah terdefinisi secara bawaan di web platform dan sudah memiliki kegunaannya masing-masing dan belum tentu sesuai dengan kebutuhan kita. Di sinilah perbedaanya dengan CustomEvent, yang mana kita bisa mendefiniskan sebuah event buatan kita sendiri untuk bisa ditangkap oleh sebuah komponen.

Di tombol di halaman checkout, kita dapat menulis logika untuk mengirimkan custom event.

// CheckoutPage.js
const handleChangeCurrencyClick = () => {
  const dropdownEvent = new CustomEvent("toggleCurrencyDropdown", {
    detail: true,
  });
  document.dispatchEvent(dropdownEvent);
}

...

<button onClick={handleChangeCurrencyClick}>Change Currency</button>

Kemudian di komponen header, kita menambahkan event listener untuk menangkap custom event yang telah kita kirim.

// Header.js
const [isDropdownOpened, setDropdownOpened] = useState(false);

const handleDropdownEvent = (e) => {
  const shouldDropdownOpen = e.detail;
  setDropdownOpened(shouldDropdownOpen);
};

useEffect(() => {
  document.addEventListener("toggleCurrencyDropdown", handleDropdownEvent);
  return () => {
    document.removeEventListener("toggleCurrencyDropdown", handleDropdownEvent);
  };
}, [handleDropdownEvent]);

Penjelasan

Di sini kita memberi nama event kita dengan "toggleCurrencyDropdown" yang sebenarnya diganti dengan nama apapun asalkan tidak menggunakan nama event bawaan yang sudah ada agar tidak terjadi konflik.

Ketika mendefinisikan custom event, kita juga dapat mengirimkan parameter dalam field detail yang dalam kasus ini berisi boolean untuk mengatur buka tutupnya dropdown.

Di komponen header, pasang sebuah event listener untuk menangkap event "toggleCurrencyDropdown" yang telah terkirim. Ketika event tersebut terjadi, kita membaca parameter yang dikirimkan di dalamnya untuk menentukan state dari dropdown.

Akhir Kata

Custom Event di sini tidak selalu cara terbaik, bisa jadi ada cara lain yang lebih baik tergantung kondisi keseluruhan kode. Namun ini dapat digunakan sebagai salah satu alternatif solusi (escape hatch) ketika mengalami kebuntuan-kebutuan tertentu. Hal ini juga sebagai pengingat bahwa sudah cukup banyak juga utilitas bawaan yang tersedia di web platform.

Daftar tautan terkait: