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
:- Impor
useEffect
dari React (barenguseState
kalau kamu pake state juga):javascript import React, { useState, useEffect } from 'react';
- Di dalem functional component-mu, panggil
useEffect()
.useEffect()
nerima dua argumen:- Fungsi Efek (Effect Function): Fungsi yang isinya kode side effect yang mau kamu jalanin. Fungsi ini bakal dijalanin sama React setelah render selesai.
- Array Dependensi (Dependency Array) - Opsional: Array ini nentuin kapan fungsi efek itu harus dijalanin ulang. Ini super penting buat ngontrol perilaku
useEffect
!
- Impor
-
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:
-
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
-
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.
-
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?
- Sebelum efek dijalanin ulang: Kalau array dependensi berubah dan fungsi efek mau dijalanin lagi, fungsi cleanup dari efek sebelumnya bakal dijalanin dulu.
- Pas komponen mau di-unmount: Kalau komponennya mau dihapus dari DOM, fungsi cleanup dari efek terakhir bakal dijalanin.
Contoh Fungsi Cleanup buat Timer:
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
:
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
:
- Panggil Hooks cuma di Level Atas (Top Level): Jangan di dalem loop, kondisi, atau nested function.
- 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?