useEffect — ez egy React hook, amely lehetővé teszi mellékhatások végrehajtását funkcionális komponensekben, helyettesítve az osztálykomponensek életciklus metódusait: componentDidMount, componentDidUpdate és componentWillUnmount. A React Documentation (2025) szerint a useEffect azután fut le, miután a React megerősítette a DOM változásait, ami garantálja a hozzáférést a jelenlegi DOM-fához. A hook elfogad egy effekt függvényt és egy opcionális függőségi tömböt, amely a végrehajtás gyakoriságát szabályozza.
Főbb pontok
useEffect — ez egy hook, amelyet a React 16.8-ban adtak hozzá mellékhatások végrehajtására funkcionális komponensekben. Mellékhatások alatt azokat a műveleteket értjük, amelyek nem kapcsolódnak közvetlenül a UI rendereléséhez: HTTP kérések API-hoz, eseményekre való feliratkozás, munka időzítőkkel, DOM-manipulációk, naplózás és harmadik féltől származó könyvtárakkal való integráció.
A hookok megjelenése előtt mindezeket a műveleteket az osztálykomponensek életciklus metódusaiba kellett helyezni: componentDidMount inicializáláshoz, componentDidUpdate a props-változásokra való reagáláshoz, componentWillUnmount tisztításhoz. A useEffect mindhárom forgatókönyvet egyetlen API-ban egyesítette, ahol a függőségi tömb határozza meg, mikor kell az effektnek elindulnia. Ez egyszerűsítette a logikát és csökkentette a kód ismétlődését, különösen az előfizetéses forgatókönyvekben.
A React DevTools Usage Survey (2024) szerint a useEffect a második legnépszerűbb hook a useState után, amelyet a React-alkalmazások 89%-ában használnak. A fejlesztők többsége adatok betöltésére, külső rendszerekkel való szinkronizálásra és DOM-eseményekre való feliratkozások kezelésére használja.
import { useEffect } from 'react';
function UserProfile({ userId }) {
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(data => setUser(data));
}, [userId]);
}
useEffect az átadott effekt függvényt azután hajtja végre, miután a React befejezte a renderelést és frissítette a DOM-ot. Ez a legfontosabb különbség a renderelés alatti számításokhoz képest: az effekt nem blokkolja a rajzolást, ami kritikus a UX-teljesítmény szempontjából. Ha az effektek szinkron módon futnának, a felhasználó egy «lefagyott» felüeletet látna az adatok betöltése közben.
Egy tipikus effekt életciklusa három fázisból áll. A komponens csatlakoztatásakor a React végrehajtja az effektet. Minden frissítésnél, ha a tömb legalább egy függősége megváltozott, a React először az előző effekt tisztító függvényét hajtja végre, majd az új effektet. A komponens leválasztásakor csak a tisztító függvény fut le.
A React Team — useEffect RFC (2024) szerint a useEffect belső megvalósítása egy mellékhatás-sort használ a fiber-fában. A változások megerősítése után (commit phase) a React bejárja ezt a sort és meghívja az effekt függvényeket a komponensben történő deklarálásuk sorrendjében. Minden fiber csomópont tárol egy referenciát az előző effektre a helyes tisztítás és újraindítás érdekében.
| Fázis | React művelete | Mikor történik |
|---|---|---|
| Csatlakoztatás | Effekt függvény meghívása | Az első renderelés után |
| Frissítés | cleanup → effekt | Függőségek változásakor |
| Leválasztás | Csak cleanup | Komponens eltávolításakor |
A függőségi tömb — a useEffect második argumentuma — meghatározza, mikor kell az effektet újraindítani. A React az Object.is segítségével hasonlítja össze a tömb minden értékét az előző rendereléssel. Ha legalább egy érték megváltozott, az effekt újra fut. Ha a tömb üres ([]), az effekt csak egyszer fut le a csatlakoztatás után.
A függőségek helyes megválasztása — a useEffect-tel való munka legnehezebb része. A tömbnek tartalmaznia kell minden változót és függvényt, amelyet az effekt belsejében használnak, és a renderelések között változhatnak. Egy függőség kihagyása stale closures-hoz vezet — az effekt egy elavult értéket «lát»” az előző renderelésből. Felesleges függőségek hozzáadása túlzott újraindításokhoz és potenciális hibákhoz vezet.
// A függőségek szabályozzák, mikor fut újra az effekt
useEffect(() => {
document.title = `User: ${user.name}`;
}, [user.name]); // csak akkor fusson újra, ha a user.name változik
// eslint-disable-next-line react-hooks/exhaustive-deps
// Ha kihagysz egy függőséget, elavult adatokat kapsz
A React biztosítja az eslint-plugin-react-hooks bővítményt az exhaustive-deps szabállyal, amely automatikusan ellenőrzi a függőségi tömb teljességét. A Meta Engineering Blog (2024) szerint ennek a bővítménynek az aktiválása 72%-kal csökkenti a hookokkal kapcsolatos hibák számát. Javasolt az összes exhaustive-deps figyelmeztetés javítása, nem pedig megjegyzéssel történő elnyomása, kivéve az egyéni logikával rendelkező ritka eseteket.
Ha egyáltalán nem adsz meg függőségi tömböt, a useEffect minden renderelés után lefut. Ez hasznos lehet a DOM-mal való szinkronizáláshoz vagy naplózáshoz, de a legtöbbször hiba: az effekt túl gyakran fut, ami teljesítményvesztéshez vezet. A legtöbb esetben üres tömböt (egyszer a csatlakoztatáskor) vagy konkrét props/state értékekkel rendelkező tömböt kell átadni.
Az üres tömb ([]) azt jelenti, hogy az effekt nem függ egyetlen értéktől sem, és szigorúan egyszer fut le. Ez a componentDidMount analógiája az osztálykomponensekben. Azonban emlékezni kell: ha az effekt belsejében props-ot vagy állapotot használnak, de azok nem szerepelnek a függőségi tömbben, az effekt a kezdeti értékeiket fogja használni, és soha nem látja a frissítéseket. Ezt stale capture-nek hívják, és gyakran nehezen felderíthető hibák forrása.
| Függőségi tömb | Viselkedés | Analógia osztályokból |
|---|---|---|
| Argumentum nélkül | Minden renderelés után | componentDidUpdate |
| [] | Egyszer a csatlakoztatáskor | componentDidMount |
| [a, b] | Amikor a vagy b változik | componentWillReceiveProps analógia |
| cleanup return | Leválasztás kezelése | componentWillUnmount |
A tisztító függvény (cleanup) — egy függvény, amelyet a useEffect visszaadhat a callback-jéből. A React akkor hívja meg, amikor a komponens leválasztásra kerül, és mielőtt az effekt újra futna a függőségek változásakor. A cleanup szükséges az előfizetések, időzítők, kérések és minden olyan erőforrás lemondásához, amelyet fel kell szabadítani.
Tipikus példa — WebSocket-előfizetés. Csatlakoztatáskor létrejőn a kapcsolat, a függőségek frissítésekor újra létrejőn (a cleanup lezárja a régit, az effekt megnyitja az újat), leválasztáskor bezáródik. Cleanup nélkül a komponens minden újracsatlakoztatása új WebSocket-kapcsolatot hozna létre, ami memóriaszivárgáshoz és több kapcsolathoz vezetne.
useEffect(() => {
const socket = new WebSocket('wss://api.example.com');
socket.onmessage = event => setData(event.data);
// Cleanup függvény — fut leválasztáskor és újrafutás előtt
return () => {
socket.close();
};
}, []);
A React Documentation (2025) szerint az AbortController a modern megközelítés a fetch kérések lemondására a cleanup-ban. Ha egy effekt HTTP kérést indít, és a komponens a kérés befejeződése előtt leválasztásra kerül, a kérés tovább fut, és a setState a leválasztás után hibát okoz. Hozz lére egy AbortController-t az effekten belül, és hívd meg a controller.abort()-ot a cleanup-ban a kérés lemondásához.
A leggyakoribb hiba — függőségek kihagyása. Például az effekt használja a userId props-t, de a függőségi tömb üres. Ennek eredményeként az effekt egyszer fut le a userId kezdeti értékével, és soha nem reagál a változásaira. A fejlesztő látja, hogy a komponens új userId-t kap, de az adatok nem frissülnek. Az eslint-plugin-react-hooks az exhaustive-deps szabállyal automatikusan felismeri az ilyen hibákat.
// ❌ Race condition — nincs lemondás
useEffect(() => {
fetch(`/api/user/${userId}`).then(res => setUser(res));
}, [userId]);
// ✅ Javítva AbortController-rel
useEffect(() => {
const controller = new AbortController();
fetch(`/api/user/${userId}`, { signal: controller.signal })
.then(res => setUser(res));
return () => controller.abort();
}, [userId]);
A végtelen ciklus problémájának megoldásához kerüld el olyan logika useEffect-be helyezését, amely az előző állapot alapján frissíti az állapotot. Használd a setState funkcionális formáját, vagy végezd el a számításokat az effekten kívül. Ha az effekt feliratkozik storage-ra vagy böngészőeseményre, győződj meg arról, hogy a figyelő példánya egyszer jön létre, ne minden renderelésnél.
Gyakran ismételt kérdések
Közvetlenül — nem, mert a useEffect egy szinkron függvény vagy undefined visszaadását várja. Ha a callback async-ként van deklarálva, az egy Promise-t ad vissza, amelyet a React figyelmen kívül hagy, és a tisztítási mechanizmus leáll. Megoldás: hívd meg az async függvényt az effekten belül: useEffect(() => { async function load() { ... }; load(); }, []).
Nincs korlátozás. A React javasolja a nem összefüggő logikák különálló useEffect-ekre bontását, még akkor is, ha ugyanaz a függőségi tömbjük. Minden effekt egyetlen világosan meghatározott mellékhatás-feladatért feleljen: egyik az előfizetésért, másik az adatok betöltéséért, harmadik a lapfül címének szinkronizálásáért. Ez leegyszerűsíti a megértést és a hibakeresést.
A React Strict Mode-ban (csak fejlesztői módban) minden effekt csatlakoztatásra, leválasztásra és újracsatlakoztatásra kerül. Ez egy funkció, nem hiba — a React ellenőrzi, hogy a tisztítás megfelelően működik-e. Ha a leválasztás és újracsatlakoztatás után az effekt helytelenül viselkedik (például az előfizetések megkettőződnek), a tisztítás nem teljes. Élesben az effekt egyszer fut le.
Használj AbortController-t. Hozz létre egy controller-t az effekten belül, add át a controller.signal-t a fetch-nek, és a cleanup-ban hívd meg a controller.abort()-ot. Ha a komponens a kérés befejeződése előtt leválasztásra kerül, a fetch lemondásra kerül, és a setState nem hívódik meg. Ez megakadályozza a race condition-t és a «Can't perform a React state update on an unmounted component» hibát.
A useEffect minden renderelés után kivétel nélkül lefut. Ez azt jelenti, hogy bármely setState az effekten belül új renderelést → új effektet → végtelen ciklust okoz. A gyakorlatban egy függőségi tömb nélküli effekt szinte mindig hiba. Kivételek — naplózás vagy külső rendszerrel való szinkronizálás, ahol minden renderelés szinkronizációt igényel.
Összefoglaló
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is