useState — уграђени React хоок који омогућава функционалним компонентама да управљају локалним стањем без претварања у класне компоненте. React 16.8 је представио хоокове, а useState је постао најчешће коришћени међу њима, заменивши this.state и this.setState из класног приступа. Према React Documentation (2025), више од 80% компоненти у модерним React апликацијама користи useState за управљање подацима форме, интерфејсним заставицама и бројачима. Хоок враћа кортеж са тренутном вредношћу и сеттер функцијом која ажурира стање и иницира поновно рендеровање компоненте.
Главно
useState — фундаментални React хоок, додат у верзији 16.8, који даје функционалним компонентама могућност да чувају и мењају локално стање. Пре појаве хоокова, стање се могло користити само у класним компонентама кроз this.state и this.setState, што је чинило функционалне компоненте искључиво презентационим. useState је уклонио ово ограничење, омогућивши писање целе апликације на функционалним компонентама.
Хоок прима један аргумент — почетну вредност стања — и враћа низ од два елемента. Први елемент је тренутна вредност стања, други — функција за његово ажурирање. React гарантује да је сеттер функција стабилна и да се не мења између рендеровања, што омогућава безбедно преношење у компоненте деце и коришћење у затворењима.
Према React DevTools Usage Survey (2024), useState се користи у 96% React апликација, што га чини најраспрострањенијим хооком у екосистему. Чак и у апликацијама које користе глобално стање кроз Redux или Zustand, локални стате кроз useState остаје главни механизам управљања UI стањем — отворени модали, вредности поља за унос, активне картице.
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>
);
}
Унутрашњи механизам useState се заснива на систему fiber чворова React-а. Свака компонента у React-у је представљена fiber чвором који чува повезану листу хоокова у облику повезане листе. Када компонента позове useState, React ствара нови чвор у овој листи и чува у њему тренутну вредност стања и референцу на ред ажурирања.
При позиву сеттер функције, React не ажурира стање одмах. Уместо тога, ставља ажурирање у ред (pending state queue), планира поновно рендеровање компоненте и тек током следећег рендеровања израчунава ново стање на основу старог и примењених ажурирања. Ово обезбеђује груписање — ако у једном руковаоцу догађаја позовете сеттер три пута, React их групише у једно поновно рендеровање.
Према React Team — React 18 Working Group (2024), аутоматско груписање је проширено у React 18: сада се ажурирања стања групишу не само у руковаоцима догађаја, већ и у setTimeout, Promise повратним позивима и домаћим руковаоцима. Ово је донело повећање перформанси до 30% у сценаријима са вишеструким ажурирањима стања.
Када ново стање зависи од претходног, користи функционалну форму сеттер-а: setCount(prev => prev + 1). React преноси функцији тренутну вредност стања у тренутку примене ажурирања, што гарантује исправност чак и при груписаним ажурирањима. Без функционалне форме setCount(count + 1) може користити застарелу вредност ако се позове више пута заредом.
// Лења иницијализација — покреће се само једном
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)
Основна синтакса useState је изузетно концизна: const [state, setState] = useState(initialValue). Почетна вредност се користи само при првом рендеровању; при наредним рендеровањима React је игнорише и враћа тренутну сачувану вредност. Ако почетно израчунавање захтева скупе операције, проследи функцију иницијализатор: useState(() => computeExpensiveInitial()).
Лења иницијализација (lazy initial state) је посебно важна када почетна вредност долази из localStorage-а, сложене трансформације података или парсирања URL параметара. React позива функцију иницијализатор само једном — при монтирању компоненте, што штеди ресурсе при наредним рендеровањима. Без лење иницијализације, скупи израз ће се израчунавати при сваком рендеровању, чак и ако се његов резултат игнорише.
| Форма | Пример | Када користити |
|---|---|---|
| Директна | useState(0) | Једноставна почетна вредност |
| Лења | useState(() => compute()) | Скупо почетно израчунавање |
| Функционални сеттер | setState(prev => prev + 1) | Ажурирање на основу претходног |
| Директни сеттер | setState(newValue) | Нова вредност не зависи од старе |
// Стање објекта — креирај нову референцу
const [user, setUser] = useState(() => {
const saved = localStorage.getItem('user');
return saved ? JSON.parse(saved) : null;
});
useState подједнако добро ради са примитивима (бројеви, стрингови, булови) и референцним типовима (низови, објекти). Међутим, постоји важна разлика: за примитиве React одређује промену по вредности, за објекте и низове — по референци. Мутација постојећег објекта без стварања новог неће изазвати поновно рендеровање, јер је референца остала иста.
При раду са објектима и низовима увек стварај нову копију са измењеним подацима. За објекте користи спред синтаксу: setUser(prev => ({...prev, name: newName})). За низове — методе које враћају нови низ: filter, map, concat, или спред синтаксу за додавање елемената. Методе мутације попут push, pop, splice директно неће радити — React ће их игнорисати, јер се референца на низ није променила.
// ✅ Исправно: хоокови на врху
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]);
Као и сви React хоокови, useState се придржава два правила. Прво: позивај хоокове само на врху компоненте — не могу се постављати унутар услова, петљи или угнежђених функција. Ово гарантује да се хоокови позивају истом редоследу при сваком рендеровању, што је критично за унутрашњу повезану листу React-а.
Друго правило: позивај хоокове само из функционалних React компоненти или прилагођених хоокова. Не позивај useState из обичних функција, повратних позива или класних компоненти. Кршење ових правила доводи до грешке Invalid hook call, коју React хвата у фази извршења.
// ❌ Проблем застарелог затворења
function GoodComponent() {
const [count, setCount] = useState(0);
const [name, setName] = useState('');
// ✅ Поправљено функционалним ажурирањем
}
// бројач је застарео!
function BadComponent() {
if (isLogged) {
const [user, setUser] = useState(null);
}
}
Најчешћа грешка — директна мутација објеката и низова уместо стварања нових референци. Програмери су навикли на мутабилни стил из класних компоненти, где је this.state.user.name = „Ново име“ радило (иако није препоручено). У функционалним компонентама таква мутација се једноставно игнорише: React не види промену референце и не прецртава компоненту.
Проблем застарелог затворења (stale closure) настаје када повратни позив прослеђен у useEffect или руковалац догађаја „xвата” застарелу вредност стања из затворења у тренутку стварања повратног позива. Решење — коришћење функционалне форме сеттера или укључивање потребних вредности у низ зависности useEffect-а. Према React Documentation — Hooks FAQ (2025), застарела затворења су други најчешћи узрок грешака у хооковима после неправилног низа зависности.
// ❌ 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);
}, []);
Често постављана питања
Да, али са опрезом. За дубоко угнежђене објекте, сваки ниво захтева копирање при ажурирању: setState(prev => ({...prev, nested: {...prev.nested, key: newValue}})). Ако имате објекте са три или више нивоа угнежђења, размотрите Immer (библиотека за неизменљиво ажурирање) или поделите стање на неколико useState за различите нивое.
useState је асинхрони у смислу да позив сеттера не ажурира вредност одмах. React ставља ажурирање у ред и извршава га при следећем рендеровању. Након setCount(newValue), променљива count у тренутној функцији још увек садржи стару вредност. Нова вредност ће бити доступна тек при следећем позиву компоненте. Механизам груписања гарантује да су вишеструки позиви груписани у једно рендеровање.
React ће бацити грешку Invalid hook call. Хоокови се могу позивати само унутар функционалних React компоненти или прилагођених хоокова (функција чије име почиње са use). Ово ограничење је уграђено у имплементацију хоокова: они користе fiber стабло компоненте за чување стања, а ван компоненте ово стабло није доступно.
useState одговара за једноставна независна стања (бројачи, поља за унос, заставице). useReducer је бољи када је стање сложени објекат са више поља, логика ажурирања зависи од типа акције или следеће стање захтева сложену трансформацију. Практично правило: ако имате више од три повезана поља стања — користите useReducer.
Ово је урађено за перформансе. Када би useState ажурирао стање синхроно, сваки позив сеттера би изазвао тренутно поновно рендеровање, што би довело до вишеструких прецртавања унутар једног руковаоца догађаја. Груписање, при којем React групише ажурирања и извршава једно поновно рендеровање, је оптимизација уведена још у React 16 и значајно побољшана у React 18 са аутоматским груписањем.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође