- Bab 6 dari 10
- 30 menit
- 1 latihan kode
- 4 soal kuis
useEffect dan useContext: efek samping dan data bersama
Di bab ini (7 bagian)
Tujuan bab ini
- Memahami apa itu efek samping dan menjalankannya dengan
useEffect. - Mengatur kapan efek berjalan lewat dependency array (tanpa array,
[], atau[nilai]) dan membersihkannya dengan cleanup. - Mengenali kesalahan umum: infinite loop, dependency yang hilang, dan efek yang jalan dua kali di StrictMode.
- Berbagi data ke banyak komponen dengan
createContext, Provider, danuseContexttanpa prop drilling.
Render harus murni, efek di luar render
Di bab sebelumnya kamu tahu bahwa komponen dipanggil ulang setiap render. Fungsi komponen sebaiknya murni: menerima props dan state, mengembalikan JSX, tanpa menyentuh dunia luar. Tapi aplikasi nyata butuh menyentuh dunia luar: memanggil API, memasang timer, membaca localStorage, mengganti judul tab browser, atau memasang event listener di window. Semua itu disebut efek samping (side effect).
Kalau kamu menaruh efek samping langsung di badan komponen, efek itu jalan di setiap render, bahkan sebelum tampilannya muncul di layar. useEffect adalah tempat resminya: kode di dalamnya dijalankan React setelah render selesai dan perubahan sudah diterapkan ke DOM.
Bentuk umumnya: useEffect(fungsiEfek, dependencyArray).
Dependency array: kapan efek dijalankan
Dependency array memberi tahu React nilai apa saja yang dipakai efek. Setelah setiap render, React membandingkan isi array dengan render sebelumnya (pakai Object.is). Kalau ada yang berbeda, efek dijalankan ulang.
| Bentuk | Kapan efek jalan | Contoh pemakaian |
|---|---|---|
Tanpa array: useEffect(fn) | Setelah setiap render | Jarang dipakai, misalnya logging |
Array kosong: useEffect(fn, []) | Sekali, setelah komponen pertama kali tampil (mount) | Memasang timer atau listener sekali |
Ada isi: useEffect(fn, [a, b]) | Saat mount, lalu setiap kali a atau b berubah | Fetch ulang saat id berubah, update judul |
Analoginya alarm di HP. Tanpa array itu alarm yang bunyi setiap kali kamu membuka HP. Array kosong itu alarm sekali saja. Array berisi nilai itu alarm yang bunyi setiap kali jadwal tertentu berubah.
Cleanup: membereskan sebelum pergi
Beberapa efek meninggalkan "sisa": timer yang terus berdetak, listener yang terus mendengar, atau koneksi yang terus terbuka. Kalau komponen sudah hilang dari layar tapi timer-nya masih jalan, terjadi memory leak dan bug aneh. Untuk itu, efek boleh mengembalikan fungsi cleanup.
Urutan kerjanya:
- Komponen tampil, React menjalankan efek: interval dipasang.
- Setiap detik
setWaktumemicu render ulang. Efek tidak jalan lagi karena dependency-nya[]. - Saat komponen dilepas (unmount), React memanggil cleanup: interval dihentikan.
Kalau dependency-nya berisi nilai, React menjalankan cleanup dari efek lama sebelum menjalankan efek baru. Jadi selalu ada pasangan pasang-lepas yang rapi.
Kesalahan umum
1. Infinite loop. Efek mengubah state, state memicu render, render menjalankan efek lagi, dan seterusnya.
Hal yang sama terjadi bila dependency berisi object atau array yang dibuat ulang di setiap render, misalnya const opsi = { page: 1 } di badan komponen lalu [opsi]. Referensinya selalu baru, jadi efek selalu jalan. Pindahkan object itu ke dalam efek, atau jadikan dependency-nya nilai primitif seperti page.
2. Dependency hilang. Efek memakai kota, tapi dependency-nya []. Akibatnya efek memakai nilai kota dari render pertama selamanya (stale value), dan data tidak ikut berubah saat kota diganti. Aturan praktisnya: semua props, state, dan variabel komponen yang dipakai di dalam efek harus masuk ke dependency array. Plugin ESLint eslint-plugin-react-hooks (aturan exhaustive-deps, sudah ada di template Vite React) akan memberi peringatan bila ada yang terlewat.
3. Efek jalan dua kali di development. Kamu melihat console.log di efek muncul dua kali dan bingung. Ini bukan bug. Template Vite membungkus aplikasi dengan <StrictMode>, dan di mode development React sengaja menjalankan mount, cleanup, mount lagi untuk menguji apakah cleanup-mu benar. Kalau timer-mu jadi dobel, artinya cleanup belum ada. Di build production, efek hanya jalan sekali. Jangan hapus StrictMode untuk "memperbaikinya", perbaiki cleanup-nya.
4. Memakai efek untuk hal yang bisa dihitung. Misalnya menyimpan namaLengkap di state lalu mengisinya lewat efek dari depan dan belakang. Cukup hitung langsung saat render: const namaLengkap = depan + " " + belakang;.
Prop drilling dan useContext
Sekarang masalah lain. Bayangkan tema gelap/terang disimpan di App, tapi yang butuh adalah Tombol yang letaknya App > Halaman > Layout > Sidebar > Tombol. Tanpa alat lain, kamu harus mengoper prop tema melewati Halaman, Layout, dan Sidebar, padahal ketiganya tidak memakainya. Ini disebut prop drilling: kode jadi panjang, dan setiap kali bentuk datanya berubah, banyak file ikut berubah.
Context menyelesaikan ini. Analoginya Wi-Fi: alih-alih menarik kabel LAN ke setiap ruangan, kamu pasang router sekali, dan perangkat mana pun di rumah bisa langsung terhubung.
Beberapa hal yang perlu kamu tahu:
useContextmencari Provider terdekat di atasnya. Kalau tidak ada Provider sama sekali, ia mengembalikan nilai default daricreateContext.- Di React 19 kamu juga boleh menulis
<TemaContext value={...}>langsung sebagai Provider. Bentuk.Providermasih berfungsi, jadi kamu akan sering melihat keduanya. - Saat
valueberubah, semua komponen yang memakai context itu dirender ulang. Karena itu context cocok untuk data global yang jarang berubah: tema, bahasa, user yang login. Untuk state kompleks yang sering berubah, pertimbangkan pola lain (misalnya useReducer atau library state management). - Context bukan pengganti props. Kalau data hanya turun satu atau dua level, oper lewat props saja, lebih jelas.
Rangkuman
- Efek samping (fetch, timer, listener, judul dokumen) ditaruh di
useEffect, yang jalan setelah render. - Tanpa array: setiap render.
[]: sekali saat mount.[a, b]: saat mount dan setiapaataubberubah. - Kembalikan fungsi cleanup untuk menghentikan timer atau melepas listener. React memanggilnya sebelum efek berikutnya dan saat unmount.
- Hindari infinite loop, masukkan semua nilai yang dipakai ke dependency, dan ingat StrictMode sengaja menjalankan efek dua kali di development.
createContext+ Provider +useContextmembagikan data ke banyak komponen tanpa prop drilling.
Slide 23 sampai 24 dari deck ReactJS. Penjelasan lengkapnya ada di mode Baca.

Selesaikan bab ini
- 1. Baca materi
- 2. Latihan kode (1)
- 3. Kuis (4 soal)
Latihan kode: Kapan efek jalan ulang, dan judul tab
Setelah setiap render, React memutuskan apakah efek dijalankan dengan membandingkan dependency array lama dan baru. Tiru logika itu sebagai fungsi murni.
perluJalan(depsLama, depsBaru)mengembalikantruebila efek harus dijalankan:depsBaruadalahundefined(tidak ada array): selalutrue.depsLamaadalahnull(render pertama):true.- Selain itu
truebila ada satu posisi yang berbeda menurutObject.is, danfalsebila semuanya sama.
judulDokumen(belumDibaca)membuat teks untukdocument.titledi efekuseEffect(() => { document.title = judulDokumen(n); }, [n]):0menghasilkan"Kotak Masuk", angka lain menghasilkan misalnya"(3) Kotak Masuk", dan lebih dari 99 menjadi"(99+) Kotak Masuk".
Cek pemahaman
1Kapan efek useEffect(fn, []) dijalankan?
2Di mode development dengan StrictMode, React sengaja menjalankan efek, cleanup, lalu efek lagi saat komponen pertama tampil.
3Kode efek mana yang menyebabkan infinite loop?
4Apa teks yang tampil, berurutan dari atas ke bawah?
const Warna = createContext("merah"); function Label() { const w = useContext(Warna); return <span>{w} </span>; } function App() { return ( <> <Label /> <Warna.Provider value="biru"> <Label /> <Warna.Provider value="hijau"> <Label /> </Warna.Provider> </Warna.Provider> </> ); }