React: Membangun Antarmuka Pengguna · 6/9
useEffect — dan kapan justru jangan dipakai
Sebagian besar effect di kode junior seharusnya tidak ada. Pelajari sedikit kasus yang memang perlu.
Baca 32 menit
Setelah pelajaran ini kamu bisa
- Menyebutkan effect itu untuk apa, dan bukan untuk apa
- Menulis dependency array dengan benar
- Selalu membersihkan subscription, timer, atau listener
- Mengenali empat effect yang seharusnya tidak ada
useEffect ada untuk satu tujuan: menyinkronkan dengan sesuatu di luar React. Sebuah subscription, timer, API browser, atau widget pihak ketiga. Kalau pekerjaannya bukan tentang dunia luar, hampir pasti ia tidak seharusnya berada di dalam effect.
import { useEffect, useState } from "react";
function WindowWidth() {
const [width, setWidth] = useState(0);
useEffect(() => {
// 1. The effect: connect to the outside world.
function handleResize() {
setWidth(window.innerWidth);
}
handleResize(); // set the initial value
window.addEventListener("resize", handleResize);
// 2. The cleanup: disconnect. React calls this before re-running,
// and when the component unmounts.
return () => window.removeEventListener("resize", handleResize);
// 3. The dependency array: when should this re-run?
}, []); // [] = only on mount, because it depends on nothing
return <p>{width}px</p>;
}Dependency array
| Ditulis sebagai | Dijalankan |
|---|---|
, []) | Sekali, setelah mount |
, [venueId]) | Setelah mount, dan setiap kali venueId berubah |
) — dihilangkan sama sekali | Setelah setiap render. Hampir selalu sebuah bug. |
React membandingkan dependency dengan Object.is — kesetaraan reference, pemeriksaan yang sama seperti hal lainnya. Itu langsung mengarah ke bug infinite loop yang dialami semua orang sekali.
Kenapa object atau array di dalam dependency array membuat effect-nya jalan terus-menerus.
Hasil
Tekan Jalankan untuk melihat hasilnya.
Ini jalan di browser kamu, di dalam sandbox. Apa pun yang kamu tulis di sini tidak bisa merusak situs.
Cleanup bukan opsional
Setiap subscription yang dibuka sebuah effect harus ditutup. Ini pelajaran kebocoran memori dari modul 3, dan React memberimu tempat yang tepat untuk melakukannya.
// Timers
useEffect(() => {
const id = setInterval(tick, 1000);
return () => clearInterval(id);
}, []);
// Listeners - the same function reference, as module 3 explained
useEffect(() => {
const onKey = (e) => { if (e.key === "Escape") close(); };
document.addEventListener("keydown", onKey);
return () => document.removeEventListener("keydown", onKey);
}, [close]);
// Fetching: cancel the result of a request that is no longer wanted
useEffect(() => {
let active = true;
loadVenue(venueId).then((data) => {
if (active) setVenue(data); // ignore a response that arrived late
});
return () => { active = false; };
}, [venueId]);LessonCompleteButton.Empat effect yang seharusnya tidak ada
// 1. Deriving a value. Just calculate it during render.
useEffect(() => { setFullName(first + " " + last); }, [first, last]); // no
const fullName = first + " " + last; // yes
// 2. Resetting state when a prop changes. Use a key instead.
useEffect(() => { setDraft(""); }, [userId]); // no
<ProfileForm key={userId} /> // yes
// 3. Responding to an event. Put it in the handler.
useEffect(() => { if (submitted) sendAnalytics(); }, [submitted]); // no
function handleSubmit() { sendAnalytics(); save(); } // yes
// 4. Fetching on mount in a Next.js app. Fetch on the server.
useEffect(() => { fetch("/api/venues").then(setVenues); }, []); // usually no
// A Server Component just awaits the data - the next module covers this.Uji yang perlu kamu terapkan: apakah ini menyinkronkan dengan sesuatu di luar React? Sebuah perhitungan tidak. Merespons sebuah klik juga tidak — handler klik-nya sudah ada dan jalan tepat di saat yang benar. Hanya koneksi ke dunia luar yang sungguhan yang memenuhi syarat.
Tugas praktik
Di proyek ini, temukan setiap useEffect — hanya ada empat, di theme-toggle.tsx, code-runner.tsx, dan lesson-complete-button.tsx. Untuk masing-masingnya, jawab: ia menyinkronkan dengan hal luar apa, apa dependency-nya, dan apakah ia melakukan cleanup? Lalu periksa apakah ada di antaranya yang bisa dihapus dengan aturan di atas.
Hasil yang diharapkan
Sebuah media query, sebuah worker, dan satu pembacaan dari server — semuanya benar-benar di luar React.
Cek pemahaman
Pilih jawaban dulu