Effect dan Perangkap Biasa
25 minitPertengahanReact
Dalam pelajaran ini
- ▸Guna
useEffectuntuk menyelaraskan dengan sesuatu di luar React (tajuk, pemasa, storage) - ▸Pilih dependency array yang betul dan tulis function cleanup
- ▸Elakkan gelung tak berkesudahan dan effect yang tidak perlu dengan mengira nilai semasa render
Idea utama
Render sepatutnya hanya mengira UI. Apabila anda perlu mencapai sesuatu di luar React — tajuk tab, pemasa, storage pelayar — letakkan kod itu dalam useEffect, yang berjalan selepas React mengemas kini skrin.
Setakat ini semuanya berada di dalam React: state masuk, JSX keluar. Tetapi aplikasi juga perlu berinteraksi dengan perkara yang tidak diurus oleh React: document.title, setInterval, localStorage, sambungan chat. Itu semua side effect, dan tempatnya ialah useEffect.
import { useEffect } from "react";
useEffect(() => {
// runs AFTER React has updated the screen
document.title = "Focus: " + task;
}, [task]); // ← dependency array: re-run when task changesDependency array
useEffect(fn)— tiada array: berjalan selepas setiap render. Jarang sekali itu yang anda mahu.useEffect(fn, [])— array kosong: berjalan sekali, selepas render pertama (apabila component di-mount).useEffect(fn, [a, b])— berjalan selepas render pertama dan sekali lagi setiap kaliaataubberubah. Senaraikan setiap nilai dari component yang digunakan oleh effect.
Cleanup (pembersihan)
Jika effect anda memulakan sesuatu — interval, langganan, event listener — return satu function yang menghentikannya. React memanggil cleanup itu sebelum menjalankan effect sekali lagi, dan apabila component itu hilang.
useEffect(() => {
if (!running) return; // nothing to start
const id = setInterval(() => {
setSeconds((s) => s + 1); // updater form: always the latest value
}, 1000);
return () => clearInterval(id); // cleanup: stop this interval
}, [running]);Kenapa s => s + 1?
Callback interval itu dicipta semasa satu render, jadi seconds di dalamnya tersekat pada nilai render tersebut. setSeconds(seconds + 1) akan asyik menetapkan 1. Bentuk updater meminta nilai terkini daripada React setiap kali.
Dalam projek React sebenar dengan <StrictMode>, React menjalankan setiap effect, cleanup-nya, dan effect itu sekali lagi semasa development. Ini memang disengajakan: cleanup yang tertinggal akan terus kelihatan. (Pratonton WANCode tidak menggunakan StrictMode.)
Perangkap: gelung tak berkesudahan
Menetapkan state di dalam effect menyebabkan render semula. Jika effect berjalan selepas setiap render, ia menetapkan state lagi, yang render lagi… selama-lamanya. React mengesan ini dan memaparkan Maximum update depth exceeded.
Berulang tanpa henti
useEffect(() => {
setCount(count + 1); // no array → runs every render
});Berjalan hanya bila perlu
useEffect(() => {
document.title = count + " clicks";
}, [count]); // only when count changesMungkin anda tidak perlukan effect
Jika sesuatu nilai boleh dikira daripada props atau state, kira sahaja semasa render. Menyalinnya ke dalam state dengan effect lebih perlahan (render tambahan) dan mudah menjadi tidak selari.
Effect yang tidak perlu
const [fullName, setFullName] = useState("");
useEffect(() => {
setFullName(first + " " + last);
}, [first, last]);Kira sahaja
const fullName = first + " " + last;Pratonton mempunyai localStorage emulasi sendiri untuk setiap pelajaran. Ia dikekalkan apabila pratonton dimuat semula, jadi anda boleh lihat nilai yang disimpan kekal — sama seperti pelayar sebenar.
Import useEffect dan tambah effect yang menetapkan document.title kepada Focus: <task> setiap kali task berubah — atau Focus Timer apabila task kosong. Guna [task] sebagai dependency array.
Semakan
- Tajuk tab mengikut task
- Task kosong memaparkan
Focus Timer - Tajuk ditetapkan dalam effect
Uji kefahaman
Apa yang anda pelajari
- ✓
useEffectberjalan selepas render untuk menyelaraskan dengan perkara di luar React: tajuk, pemasa, storage, sambungan. - ✓Dependency array menentukan bila ia berjalan semula; senaraikan setiap nilai yang digunakan oleh effect.
- ✓Return cleanup untuk menghentikan apa sahaja yang anda mulakan (
clearInterval, buang listener). - ✓Menetapkan state dalam effect tanpa array akan berulang selama-lamanya; nilai yang boleh dikira langsung tidak perlukan effect.
Output konsol daripada kod anda akan dipaparkan di sini.