useState — egy beépített React hook, amely lehetővé teszi a funkcionális komponensek számára, hogy osztálykomponensekké alakítás nélkül kezeljék a lokális állapotot. A React 16.8 bevezette a hook-okat, és a useState lett a leggyakrabban használt ezek közül, felváltva a this.state és this.setState osztály alapú megközelítést. A React Documentation (2025) szerint a modern React alkalmazások komponenseinek több mint 80%-a használja a useState-t űrlapadatok, interfész jelzők és számlálók kezelésére. A hook egy tuple-t ad vissza a jelenlegi értékből és egy setter függvényből, amely frissíti az állapotot és elindítja a komponens újrarenderelését.
Főbb pontok
useState — a React alapvető hook-ja, amely a 16.8 verzióban került hozzáadásra, és lehetővé teszi a funkcionális komponensek számára a lokális állapot tárolását és módosítását. A hook-ok megjelenése előtt az állapot csak osztálykomponensekben volt használható a this.state és this.setState segítségével, ami a funkcionális komponenseket kizárólag prezentációs célokra tette alkalmassá. A useState megszüntette ezt a korlátozást, lehetővé téve a teljes alkalmazás funkcionális komponensekkel történő megírását.
A hook egy argumentumot fogad — az állapot kezdeti értékét — és egy két elemből álló tömböt ad vissza. Az első elem az állapot jelenlegi értéke, a második a függvény annak frissítésére. A React garantálja, hogy a setter függvény stabil és nem változik a renderelések között, ami lehetővé teszi annak biztonságos átadását gyermekkomponenseknek és használatát closure-ökben.
A React DevTools Usage Survey (2024) szerint a useState a React alkalmazások 96%-ában használatos, így ez a legelterjedtebb hook az ökoszisztémában. Még a Redux vagy Zustand segítségével globális állapotot használó alkalmazásokban is a useState-en keresztüli lokális state marad a UI állapot kezelésének fő mechanizmusa — nyitott modálok, beviteli mezők értékei, aktív lapok.
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
A useState belső mechanizmusa a React fiber csomópontrendszerén alapul. A React-ben minden komponenst egy fiber csomópont képvisel, amely a hozzá kapcsolódó hook-ok listáját láncolt lista formájában tárolja. Amikor a komponens meghívja a useState-t, a React létrehoz egy új csomópontot ebben a listában, és eltárolja benne az állapot aktuális értékét és egy hivatkozást a frissítési sorra.
A setter függvény meghívásakor a React nem frissíti azonnal az állapotot. Ehelyett a frissítést egy sorba helyezi (pending state queue), ütemezi a komponens újrarenderelését, és csak a következő renderelés során számítja ki az új állapotot a régi és az alkalmazott frissítések alapján. Ez biztosítja a batch feldolgozást — ha egy eseménykezelőben háromszor hívod meg a setter-t, a React egyetlen újrarenderelésbe csoportosítja azokat.
A React Team — React 18 Working Group (2024) szerint az automatikus batch feldolgozás kibővült a React 18-ban: mostantól az állapotfrissítések nem csak eseménykezelőkben, hanem setTimeout, Promise callback-ekben és natív kezelőkben is csoportosításra kerülnek. Ez akár 30%-os teljesítménynövekedést eredményezett a többszörös állapotfrissítési forgatókönyvekben.
Amikor az új állapot függ az előzőtől, használd a setter funkcionális formáját: setCount(prev => prev + 1). A React a függvénynek a frissítés alkalmazásának pillanatában érvényes állapotértéket adja át, ami garantálja a helyességet még a batch-elt frissítések esetén is. Funkcionális forma nélkül a setCount(count + 1) elavult értéket használhat, ha többször egymás után hívják meg.
// Lusta inicializálás — csak egyszer fut le
setCount(prev => prev + 1);
setCount(prev => prev + 1);
setCount(prev => prev + 1);
// Result: count increased by 3
// NOT batch-safe: stale closure
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
// Result: count increased by 1 (stale closure)
A useState alap szintaxisa rendkívül tömör: const [state, setState] = useState(initialValue). A kezdeti érték csak az első rendereléskor használatos; a következő rendereléseknél a React figyelmen kívül hagyja és a jelenleg tárolt értéket adja vissza. Ha a kezdeti számítás költséges műveleteket igényel, adj meg egy inicializáló függvényt: useState(() => computeExpensiveInitial()).
A lusta inicializálás (lazy initial state) különösen fontos, ha a kezdeti érték localStorage-ból, összetett adatátalakításból vagy URL paraméterek feldolgozásából származik. A React az inicializáló függvényt csak egyszer hívja meg — a komponens csatlakoztatásakor, ami erőforrásokat takarít meg a későbbi rendereléseknél. Lusta inicializálás nélkül a költséges kifejezés minden rendereléskor kiértékelésre kerül, még akkor is, ha az eredményét figyelmen kívül hagyják.
| Forma | Példa | Mikor használjuk |
|---|---|---|
| Közvetlen | useState(0) | Egyszerű kezdeti érték |
| Lusta | useState(() => compute()) | Költséges kezdeti számítás |
| Funkcionális setter | setState(prev => prev + 1) | Frissítés az előző alapján |
| Közvetlen setter | setState(newValue) | Az új érték nem függ a régitől |
// Objektum állapot — hozz létre új referenciát
const [user, setUser] = useState(() => {
const saved = localStorage.getItem('user');
return saved ? JSON.parse(saved) : null;
});
A useState egyaránt jól működik primitívekkel (számok, karakterláncok, logikai értékek) és referencia típusokkal (tömbök, objektumok). Van azonban egy fontos különbség: primitívek esetén a React a változást érték alapján, objektumok és tömbök esetén pedig referencia alapján érzékeli. Egy meglévő objektum mutációja új létrehozása nélkül nem vált ki újrarenderelést, mert a referencia változatlan maradt.
Objektumokkal és tömbökkel való munka során mindig készíts új másolatot a módosított adatokkal. Objektumokhoz használd a spread szintaxist: setUser(prev => ({...prev, name: newName})). Tömbökhöz — olyan metódusokat, amelyek új tömböt adnak vissza: filter, map, concat, vagy a spread szintaxist elemek hozzáadásához. A mutációs metódusok, mint a push, pop, splice közvetlenül nem fognak működni — a React figyelmen kívül hagyja őket, mert a hivatkozás a tömbhöz nem változott.
// ✅ Helyes: hook-ok a legfelső szinten
const [form, setForm] = useState({ name: '', email: '' });
const updateField = (field, value) =>
setForm(prev => ({ ...prev, [field]: value }));
// ...
const [items, setItems] = useState([]);
const addItem = item =>
setItems(prev => [item, ...prev]);
Mint minden React hook, a useState is két szabályt követ. Először is: a hook-okat csak a komponens legfelső szintjén hívd — nem helyezhetők el feltételekben, ciklusokban vagy beágyazott függvényekben. Ez garantálja, hogy a hook-ok minden rendereléskor ugyanabban a sorrendben kerülnek meghívásra, ami kritikus a React belső láncolt listája számára.
Második szabály: a hook-okat csak funkcionális React komponensekből vagy egyedi hook-okból hívd. Ne hívd a useState-t közönséges függvényekből, callback-ekből vagy osztálykomponensekből. E szabályok megsértése Invalid hook call hibához vezet, amelyet a React a végrehajtás során észlel.
// ❌ Elavult closure probléma
function GoodComponent() {
const [count, setCount] = useState(0);
const [name, setName] = useState('');
// ✅ Javítva funkcionális frissítéssel
}
// a számláló elavult!
function BadComponent() {
if (isLogged) {
const [user, setUser] = useState(null);
}
}
A leggyakoribb hiba — objektumok és tömbök közvetlen mutációja új referenciák létrehozása helyett. A fejlesztők hozzászoktak a mutábilis stílushoz az osztálykomponensekből, ahol a this.state.user.name = „Új név” működött (bár ott sem volt ajánlott). Funkcionális komponensekben az ilyen mutáció egyszerűen figyelmen kívül marad: a React nem látja a referencia változását és nem rajzolja újra a komponenst.
Az elavult closure (stale closure) problémája akkor merül fel, amikor egy useEffect-nek vagy eseménykezelőnek átadott callback „elkapja” az állapot elavult értékét a closure-ből a callback létrehozásának pillanatában. Megoldás — a setter funkcionális formájának használata vagy a szükséges értékek belefoglalása a useEffect függőségi tömbjébe. A React Documentation — Hooks FAQ (2025) szerint az elavult closure-ök a második leggyakoribb okai a hook-okkal kapcsolatos hibáknak a helytelen függőségi tömb után.
// ❌ Stale closure problem
useEffect(() => {
const timer = setInterval(() => {
setCount(count + 1); // count is stale!
}, 1000);
return () => clearInterval(timer);
}, []);
// ✅ Fixed with functional update
useEffect(() => {
const timer = setInterval(() => {
setCount(prev => prev + 1);
}, 1000);
return () => clearInterval(timer);
}, []);
Gyakran Ismételt Kérdések
Igen, de óvatossággal. Mélyen beágyazott objektumok esetén minden szint másolást igényel a frissítés során: setState(prev => ({...prev, nested: {...prev.nested, key: newValue}})). Ha három vagy több beágyazási szinttel rendelkező objektumaid vannak, fontold meg az Immer (változtathatatlan frissítés könyvtár) használatát, vagy oszd fel az állapotot több useState-re különböző szintekhez.
A useState abban az értelemben aszinkron, hogy a setter meghívása nem frissíti azonnal az értéket. A React a frissítést sorba helyezi és a következő renderelés során hajtja végre. A setCount(newValue) után a count változó a jelenlegi függvényben még mindig a régi értéket tartalmazza. Az új érték csak a komponens következő meghívásakor lesz elérhető.
A React Invalid hook call hibát dob. A hook-ok csak funkcionális React komponenseken vagy egyedi hook-okon belül hívhatók (olyan függvények, amelyek neve use-val kezdődik). Ez a korlátozás a hook-ok implementációjába van beépítve: a komponens fiber fáját használják az állapot tárolására, és a komponensen kívül ez a fa nem érhető el.
A useState egyszerű független állapotokhoz alkalmas (számlálók, beviteli mezők, jelzők). A useReducer jobb, ha az állapot egy összetett objektum több mezővel, a frissítési logika függ a művelet típusától, vagy a következő állapot összetett átalakítást igényel. Gyakorlati szabály: ha háromnál több összefüggő állapotmeződ van — használj useReducer-t.
Ez a teljesítmény érdekében történik. Ha a useState szinkron módon frissítené az állapotot, minden setter hívás azonnali újrarenderelést okozna, ami többszörös újrarajzoláshoz vezetne egy eseménykezelőn belül. A batch feldolgozás, ahol a React csoportosítja a frissítéseket és egyetlen újrarenderelést hajt végre, egy optimalizálás, amelyet már a React 16-ban bevezettek, és jelentősen továbbfejlesztettek a React 18-ban az automatikus batch feldolgozással.
Összefoglalás
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