K

Command Palette

Search for a command to run...

Daftar

Hook `useEffect` di React

Pelajari cara menggunakan hook `useEffect` di ReactJS untuk menjalankan 'efek samping' (side effects) seperti mengambil data dari API, langganan, atau memanipulasi DOM secara manual setelah komponen di-render.

Komponen "Beraksi" Setelah Tampil: Jurus useEffect Buat Side Effects!

Udah bisa bikin komponen yang punya state (useState) dan ngerespon input pengguna (event handling)? Keren banget! Komponenmu udah mulai "hidup". Tapi, gimana kalau komponenmu butuh ngelakuin sesuatu yang di luar tugas utamanya nge-render UI?

Misalnya:

  • Ngambil data dari API pas komponen pertama kali muncul.
  • Ngeset judul dokumen HTML (document.title) berdasarkan state komponen.
  • Ngedaftarin event listener ke window (misal, buat deteksi scroll atau resize) dan ngapusnya pas komponen ilang.
  • Ngejalanin timer (setInterval) dan ngentinya pas komponen ilang.
  • Berlangganan (subscribe) ke sumber data eksternal.

Nah, semua aksi kayak gini, yang "berinteraksi sama dunia luar" di luar alur render React murni, itu disebut Side Effects (Efek Samping). Dan di Functional Components, cara kita nanganin side effects ini adalah pake hook sakti bernama useEffect.

Apa Itu Side Effect di React?

Di React, fungsi utama komponen itu adalah ngambil props dan state, terus nge-return JSX yang ngedeskripsiin UI. Proses ini harusnya "murni" (pure), artinya kalau dikasih input (props & state) yang sama, hasilnya (JSX) juga harus selalu sama, dan gak boleh ngubah apa-apa di luar dirinya sendiri selama proses render.

Side Effect adalah segala sesuatu yang dilakuin komponenmu yang berinteraksi dengan "dunia luar" di luar React, atau yang punya efek berkelanjutan. Contohnya ya yang udah disebutin di atas: manipulasi DOM manual, fetch data, langganan, timer, dll.

Kenapa disebut "efek samping"? Karena aksi-aksi ini terjadi "di samping" proses render utama.

Hook useEffect: "Mesin" Buat Nanganin Side Effects

Hook useEffect ngasih kita cara buat ngejalanin kode (fungsi efek) SETELAH React selesai nge-update DOM (setelah komponen di-render atau di-re-render).

  • Cara Pake useEffect:

    1. Impor useEffect dari React (bareng useState kalau kamu pake state juga):
      javascript
      import React, { useState, useEffect } from 'react';
    2. Di dalem functional component-mu, panggil useEffect().
      • useEffect() nerima dua argumen:
        1. Fungsi Efek (Effect Function): Fungsi yang isinya kode side effect yang mau kamu jalanin. Fungsi ini bakal dijalanin sama React setelah render selesai.
        2. Array Dependensi (Dependency Array) - Opsional: Array ini nentuin kapan fungsi efek itu harus dijalanin ulang. Ini super penting buat ngontrol perilaku useEffect!
  • Sintaks Dasar useEffect:

    jsx
    useEffect(() => {
      // Kode side effect kamu ada di sini
      // Misalnya: fetch data, set judul dokumen, dll.
     
      // (Opsional) Return sebuah fungsi cleanup
      return () => {
        // Kode cleanup ada di sini (misalnya, batalin langganan, clear timer)
        // Dijalanin sebelum efek jalan lagi (kalau dependensi berubah)
        // ATAU pas komponen mau di-unmount (dihapus dari DOM)
      };
    }, [array, dependensi, opsional]); // Array dependensi

Mengontrol Kapan Efek Dijalanin: Array Dependensi Itu Kunci!

Perilaku useEffect sangat bergantung sama argumen keduanya, yaitu Array Dependensi:

  1. Array Dependensi Kosong ([]):

    • Fungsi efek cuma bakal dijalanin SATU KALI aja: yaitu setelah komponen pertama kali di-render (mounted).
    • Fungsi cleanup (kalau ada) bakal dijalanin pas komponen mau di-unmount (dihapus dari DOM).
    • Ini cocok banget buat:
      • Ngambil data dari API pas komponen pertama kali muncul.
      • Ngedaftarin event listener global (kayak ke window) yang cuma perlu sekali.
      • Ngeset timer atau interval.
    jsx
    useEffect(() => {
      console.log("Komponen sudah di-mount! Ambil data awal...");
      // fetch('/api/data').then(...);
     
      return () => {
        console.log("Komponen mau di-unmount! Bersih-bersih...");
        // batalin langganan, clear timer, dll.
      };
    }, []); // Array kosong, jadi efek cuma jalan sekali pas mount, cleanup pas unmount
  2. Array Dependensi Diisi dengan Variabel ([propA, stateB]):

    • Fungsi efek bakal dijalanin setelah render pertama, DAN bakal dijalanin ulang setiap kali salah satu nilai di dalem array dependensi itu berubah antar render.
    • React bakal ngebandingin nilai-nilai di array dependensi dari render sebelumnya sama render saat ini. Kalau ada yang beda, fungsi efek (dan fungsi cleanup dari efek sebelumnya) bakal dijalanin lagi.
    • Ini cocok buat:
      • Ngejalanin efek yang bergantung sama props atau state tertentu.
      • Ngambil data ulang dari API kalau ID produk (misal, dari prop) berubah.
      • Ngedaftarin ulang event listener kalau ada sesuatu yang berubah.
    jsx
    useEffect(() => {
      console.log(`Nilai 'hitungan' berubah jadi: ${hitungan}`);
      document.title = `Kamu sudah klik ${hitungan} kali`; // Update judul dokumen
     
      // Gak ada cleanup di sini, tapi bisa aja ada kalau perlu
    }, [hitungan]); // Efek ini jalan ulang setiap kali state 'hitungan' berubah

    PENTING: Semua variabel (dari scope komponen, termasuk props dan state) yang dipake di dalem fungsi efek itu idealnya harus kamu masukin ke array dependensi. Kalau enggak, kamu bisa dapet nilai yang "basi" (stale) atau efeknya gak jalan sesuai harapan. ESLint plugin buat React biasanya bakal ngasih warning kalau kamu lupa.

  3. Array Dependensi Tidak Dikasih Sama Sekali (Dihilangkan):

    • useEffect(() => { ... }); (tanpa argumen kedua)
    • HATI-HATI! Kalau kamu gak ngasih array dependensi, fungsi efek bakal dijalanin SETELAH SETIAP KALI komponen di-render atau di-re-render, gak peduli apa penyebab re-render-nya.
    • Ini seringkali bukan yang kamu mau dan bisa nyebabin infinite loop kalau fungsi efekmu sendiri nge-trigger update state yang bikin re-render lagi.
    • Kapan mungkin dipake? Jarang banget. Mungkin kalau efeknya bener-bener harus sinkron sama tiap render dan gak nyebabin loop. Tapi, hampir selalu lebih baik kamu tentuin dependensinya secara eksplisit.
    • Saran: Selalu usahakan kasih array dependensi. Kalau efekmu gak bergantung sama apa-apa dan cuma mau jalan sekali pas mount, kasih array kosong [].

Fungsi Cleanup di useEffect: "Beres-Beres" Setelah Efek

Kadang, side effect yang kita jalanin itu butuh "dibersihin" atau "dibatalkan" biar gak nyebabin masalah (kayak memory leak atau perilaku aneh) pas komponennya udah gak dibutuhin lagi (di-unmount) atau pas efeknya mau dijalanin ulang dengan nilai dependensi baru.

  • Caranya adalah dengan nge-return sebuah fungsi dari dalem fungsi efekmu. Fungsi return ini yang bakal jadi fungsi cleanup.
  • Kapan Fungsi Cleanup Dijalanin?
    1. Sebelum efek dijalanin ulang: Kalau array dependensi berubah dan fungsi efek mau dijalanin lagi, fungsi cleanup dari efek sebelumnya bakal dijalanin dulu.
    2. Pas komponen mau di-unmount: Kalau komponennya mau dihapus dari DOM, fungsi cleanup dari efek terakhir bakal dijalanin.

Contoh Fungsi Cleanup buat Timer:

jsx
import React, { useState, useEffect } from 'react';
 
function TimerDetik() {
  const [detik, setDetik] = useState(0);
 
  useEffect(() => {
    console.log("Efek timer dimulai atau di-reset.");
    // Ngeset interval yang bakal nambahin 'detik' tiap 1 detik
    const intervalId = setInterval(() => {
      setDetik(prevDetik => prevDetik + 1);
    }, 1000);
 
    // Ini fungsi cleanup! Bakal dijalanin pas komponen di-unmount
    return () => {
      console.log("Cleanup timer! Interval dihentikan.");
      clearInterval(intervalId); // Penting buat ngehentiin interval biar gak jalan terus di background
    };
  }, []); // Array kosong, jadi efek & cleanup cuma jalan sekali pas mount & unmount
 
  return <p>Timer: {detik} detik</p>;
}
 
export default TimerDetik;

Kalau kita gak clearInterval di fungsi cleanup, intervalnya bakal jalan terus meskipun komponen TimerDetik udah gak ditampilin lagi, ini bisa nyebabin memory leak dan bug.

Contoh Cleanup buat Event Listener di window:

jsx
useEffect(() => {
  const handleResize = () => console.log("Ukuran jendela berubah:", window.innerWidth);
  window.addEventListener('resize', handleResize);
 
  return () => {
    window.removeEventListener('resize', handleResize); // Hapus listener pas unmount
  };
}, []);

Aturan Penting Soal Hooks (Berlaku juga buat useEffect)

Inget lagi aturan Hooks dari materi useState:

  1. Panggil Hooks cuma di Level Atas (Top Level): Jangan di dalem loop, kondisi, atau nested function.
  2. Panggil Hooks cuma dari Functional Components React (atau dari Custom Hooks lain, bukan dari fungsi JavaScript biasa).

Kapan useEffect Itu Berguna Banget?

  • Fetch Data dari API: Ngambil data pas komponen pertama kali muncul (useEffect(..., [])) atau pas ada prop/state tertentu berubah (useEffect(..., [propId])).
  • Langganan (Subscriptions): Misalnya, langganan ke WebSocket atau event source eksternal. Jangan lupa cleanup buat unsubscribe.
  • Manipulasi DOM Manual (Kalau Terpaksa): Kadang kita perlu ngoprek DOM langsung (misal, fokus ke input field, atau integrasi sama library non-React). useEffect tempat yang pas buat ini karena dia jalan setelah DOM di-update React.
  • Ngeset Timer atau Interval.
  • Logging atau Analitik: Ngirim data analitik pas state tertentu berubah.

Hook useEffect ini adalah alat yang super fleksibel buat nanganin berbagai macam side effects di functional component React. Kunci utamanya adalah ngertiin cara kerja array dependensi buat ngontrol kapan efekmu dijalanin, dan jangan lupa fungsi cleanup kalau efekmu butuh "diberesin".

Awalnya mungkin kerasa agak beda sama lifecycle methods di Class Components (kalau kamu pernah liat), tapi useEffect ini sebenernya nyatuin banyak konsep lifecycle jadi satu API yang lebih simpel dan powerful.

Teruslah bereksperimen dengan useEffect buat berbagai kebutuhan. Ini bakal jadi salah satu hook yang paling sering kamu pake!


Kuis Hook `useEffect` di ReactJS

Pertanyaan 1 dari 5

Apa tujuan utama dari hook `useEffect` dalam sebuah Functional Component React?