useRef — је React хук који креира мутабилни реф објекат са својством .current, који се чува између рендеровања компоненте. За разлику од useState, промена .current не изазива поновно рендеровање, што чини useRef идеалним за чување DOM референци, тајмера и било којих вредности које треба да преживе рендеровање без поновног исцртавања UI. Према React Documentation (2025), реф објекат се креира једном током живота компоненте и не мења се између рендеровања, што гарантује стабилност референце.
Главне тачке
useRef — је хук додат у React 16.8, који враћа мутабилни реф објекат са једним својством .current. Почетна вредност се додељује .current приликом монтирања компоненте. Главна разлика у односу на обичну променљиву — реф објекат преживљава поновна рендеровања: при поновном рендеровању, React не креира поново реф, већ враћа исти објекат.
Унутрашња имплементација useRef користи исти механизам као useState и useEffect — повезану листу хукова на fiber чвору. Међутим, за разлику од useState, React не прати промене реф објекта, не ставља ажурирања у ред и не планира поновно рендеровање. Ово чини useRef изузетно лаганим хуком који не утиче на перформансе чак ни при честим променама.
Према React Team — Hooks FAQ (2025), useRef је у суштини „кутија“ која чува вредност. Синтаксни шећер: const ref = useRef(initialValue) је еквивалентно const ref = { current: initialValue } с тим што React гарантује да ће реф објекат бити исти при сваком рендеровању. Без магије — само стабилна референца којом управља React.
import { useRef } from 'react';
function Component() {
const countRef = useRef(0);
// countRef.current = 0 почетно
// countRef.current = 5 после мутације
// Нема поновног рендеровања!
}
Најчешћи сценариј коришћења useRef — добијање директног приступа DOM елементу. React додељује elementRef.current референцу на DOM чвор након монтирања компоненте. Ово је неопходно за фокусирање input-а, мерење димензија елемента, интеграцију са библиотекама за анимације и библиотекама које не користе React рендеровање.
React аутоматски управља реф референцама на DOM: при монтирању додељује стварни DOM чвор, при демонтирању га ресетује (поставља null). Ово гарантује да је у .current увек ажурна вредност и спречава цурење меморије кроз „висеће“ референце на обрисане елементе. Није потребно ручно чишћење.
function AutoFocusInput() {
const inputRef = useRef(null);
useEffect(() => {
// Фокусирај input након монтирања компоненте
inputRef.current?.focus();
}, []);
return <input ref={inputRef} type="text" />;
}
Према React — Refs and DOM documentation (2025), не користи ref за декларативне операције — отварање/затварање модала, управљање видљивошћу. У те сврхе постоје state и props. Ref-ови су намењени за императивне операције које се не могу изразити декларативно: фокус, селекција текста, интеграција са библиотекама трећих страна.
Други по важности сценариј — чување произвољних вредности које треба да се сачувају између рендеровања, али чија промена не би требало да изазове поновно рендеровање. Типични примери: идентификатори тајмера (setInterval/setTimeout), заставице за отказивање захтева, претходне вредности пропсова за поређење и сви подаци који не утичу на излаз UI.
Ово је посебно корисно у useEffect: useRef чува идентификатор тајмера, а cleanup га чисти. Ако се timerId чува у useState, сваки позив setTimerId би изазвао непотребно поновно рендеровање које није потребно ни за логику ни за UI. useRef решава овај проблем без overhead-а и без непотребних прецртавања.
function Timer() {
const intervalRef = useRef(null);
const start = () => {
intervalRef.current = setInterval(() => {
console.log('откуцај');
}, 1000);
};
const stop = () => {
clearInterval(intervalRef.current);
};
useEffect(() => stop, []);
return <><button onClick={start}>Start</button><button onClick={stop}>Stop</button></>;
}
Главна дилема — избор између useRef и useState — решава се једним питањем: „Да ли је потребно поновно рендеровање при промени вредности?“. Ако да — useState. Ако не — useRef. useState чува стање које утиче на излаз компоненте; useRef чува податке потребне за унутрашњу логику, али не утиче на UI.
У пракси, програмери често користе useRef за чување callback-ова како би избегли проблеме са затварањима. На пример, ако useEffect претплаћује на догађај и унутар callback-а је потребно ажурно state — чувај callback у useRef. При сваком рендеровању ажурирај ref.current новом функцијом, а ефекат ће увек позивати свеж callback без поновне претплате.
| Критеријум | useRef | useState |
|---|---|---|
| Поновно рендеровање | Не изазива при промени | Изазива при сваком setState |
| Мутација | Директна: ref.current = value | Преко setter-а: setState(value) |
| Коришћење у JSX | Не користи се (без ефекта) | Користи се у излазу компоненте |
| Пример | Тајмери, DOM референце, претходне вредности | Подаци форме, UI стање, заставице |
Постоји анти-шаблон: коришћење useRef за чување података који су потребни у JSX, али чија промена не би требало да изазове поновно рендеровање. То доводи до десинхронизације — UI приказује старе податке, иако је ref.current већ нов. Ако се вредност приказује у UI — користи useState. Ако се користи само унутар логике — useRef.
Комбинација useRef + useEffect — стандардни шаблон за праћење претходних вредности пропсова. Чувај претходну вредност у ref, упореди је са тренутном у useEffect и донеси одлуку на основу разлике. Ово је посебно корисно код анимација, када треба знати која је вредност била пре промене.
function PriceDisplay({ price }) {
const prevPriceRef = useRef(price);
useEffect(() => {
const prevPrice = prevPriceRef.current;
if (price > prevPrice) {
animateUp();
} else if (price < prevPrice) {
animateDown();
}
prevPriceRef.current = price;
}, [price]);
return <span>${price}</span>;
}
Према React Documentation — Hooks FAQ (2025), овај шаблон се назива „previous value pattern“. Функционише јер useRef чува вредност између рендеровања, а useEffect се извршава након потврде промена. Прво се DOM ажурира новим price, затим useEffect упоређује са претходним (који је још увек у ref) и ажурира ref.current на тренутну вредност.
Најчешћа грешка — читање ref.current у фази рендеровања за израчунавање JSX-а. Пошто промена ref.current не изазива поновно рендеровање, компонента може користити застарелу вредност. Ако вредност .current учествује у излазу UI — користи useState. Ако треба да синхронизујеш ref и state, користи useEffect за ажурирање state-а из ref-а.
// ❌ Не читај ref.current током рендеровања за приказ
function BadComponent() {
const valRef = useRef(0);
return <p>{valRef.current}</p>; // НЕЋЕ се ажурирати при мутацији
}
// ✅ Користи state за приказ, ref за логику
function GoodComponent() {
const [val, setVal] = useState(0);
const valRef = useRef(0);
return <p>{val}</p>;
}
Још једна честа грешка — коришћење useRef као јединог начина чувања стања у компоненти, када подаци ипак утичу на UI. Програмери бирају useRef да би избегли „непотребна“ поновна рендеровања, али на крају добијају UI који се не ажурира. Правилан приступ: користи useState за UI податке и useRef само за помоћне вредности које не учествују у рендеровању.
Често постављана питања
Да, ово је уобичајен шаблон — previous state pattern. Направи ref и ажурирај га у useEffect при свакој промени праћене вредности. У тренутку између рендеровања и ефекта, ref.current садржи претходну вредност која се може упоредити са тренутном. Ово не захтева додатна поновна рендеровања и ради са било којим типовима података.
React додељује ref.current вредност DOM чвора тек након што је елемент рендерован и додат у стварни DOM. Током првог рендеровања, компонента још није монтирана, зато је ref.current једнак почетној вредности (null). Приступ DOM-у преко ref.current могућ је само у useEffect или у handler-има догађаја који се позивају након монтирања.
createRef креира нови реф објекат при сваком рендеровању — треба га користити само у класним компонентама. useRef креира ref једном и враћа исти објекат при свим наредним рендеровањима. У функционалним компонентама користи искључиво useRef; createRef ће довести до губитка вредности при поновном рендеровању, јер ће објекат бити поново креиран.
Да, реф објекат се може пренети као обичан prop: <Child inputRef={inputRef} />. Дете компонента га користи преко inputRef.current. Међутим, за пренос ref-а директно на DOM елемент дете компоненте користи forwardRef — HOC који омогућава преношење ref-а кроз props. Без forwardRef, ref неће бити аутоматски повезан са DOM елементом унутар дете компоненте.
Прикачи ref на елемент, затим у useEffect читај ref.current.getBoundingClientRect() или ref.current.offsetWidth / offsetHeight. За реактивно праћење промена величине користи ResizeObserver унутар useEffect: креирај observer, претплати се на промене и ажурирај state новим димензијама. Не заборави да искључиш observer у cleanup-у.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође