useContext — је Реакт хук који функционалним компонентама пружа директан приступ подацима из контекста креираног кроз createContext. Контекст у React-у решава проблем props drilling — преношење props-а кроз више посредних компонената који сами не користе ове податке. Према React Documentation (2025), useContext прихвата објекат контекста и враћа тренутну вредност постављену од најближег Provider-а изнад у дрвету компонената. Када се вредност у Provider-у промени, сви компоненти који користе useContext се аутоматски поново исцртавају.
Главно
useContext — је хук додат у React 16.8 заједно са осталим хуковима, који омогућава читање вредности из React контекста. Контекст је уграђени механизам у React-у, намењен за преношење података кроз дрво компонената без потребе за ручним преношењем props-а на сваком нивоу. useContext замењује Consumer компоненту из старог Context API-ја и чини код концизнијим и читљивијим.
Типични сценарији коришћења контекста укључују теме изгледа (светла/тамна), локалне поставке и преводе (i18n), аутентификацију корисника, поставке апликације и све друге глобалне податке који су потребни бројним компонентима на различитим нивоима угњежђења. React тим препоручује коришћење контекста за податке које су глобалне за поддрво компонената, али не за целу апликацију.
Према React Team — Context documentation (2025), неправилно коришћење контекста је један од главних узрока проблема са перформансама у React апликацијама. Свака промена вредности у Provider-у изазива поновно исцртавање свих корисника, без обзира на то који део података се променио. Оптимизација кроз useMemo и подела контекста решава овај проблем.
import { createContext, useContext } from 'react';
// Креирај контекст са подразумеваном вредношћу
const ThemeContext = createContext('светло');
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button className={`btn-${theme}`}>Click</button>;
}
Механизам контекста у React-у је имплементиран кроз Provider-Consumer образац. createContext враћа објекат са два ентитета: Provider — компонента која преноси вредност, и сам објекат контекста који се користи у useContext-у. Provider се монтира у дрвету компонената и преноси вредност свим потомцима без обзира на дубину угњежђења.
Када React наиђе на позив useContext, пење навише кроз fiber дрво у потрази за најближим Provider-ом за дати контекст. Ако се Provider пронађе, враћа се његова вредност. Ако се Provider не пронађе, враћа се подразумевана вредност прослеђена createContext-у. Ово претраживање се дешава при сваком исцртавању, али захваљујући мемоизацији fiber чворова је веома брзо и не утиче на перформансе.
Према React — Context internals (2024), унутрашња имплементација useContext-а користи повезану листу хукова, слично useState-у. Сваки хук чува референцу ка fiber чвору, што омогућава React-у да брзо одреди који Provider одговара датом контексту. Ако Provider ажурира вредност, React означава све fiber чворове који користе овај контекст за поновно исцртавање.
Provider компоненте се могу угњездивати једна у другу, стварајући хијерархију контекста. Сваки потомак Provider-а прегаза вредност родитеља за своје поддрво. Ово је корисно када је на једном екрану потребна светла тема, а у угњежденом модалном прозору — тамна. useContext увек враћа вредност најближег Provider-а изнад у дрвету.
const UserContext = createContext(null);
const ThemeContext = createContext('светло');
function App() {
return (
<UserContext.Provider value={{ name: 'Alice' }}>
<ThemeContext.Provider value='dark'>
<Profile />
</ThemeContext.Provider>
</UserContext.Provider>
);
}
Функција createContext(defaultValue) креира објекат контекста. Параметар defaultValue се користи када компонента позове useContext, али изнад у дрвету нема одговарајућег Provider-а. Без defaultValue, useContext ће вратити undefined, што може довести до неочекиваних грешака. Препоручује се увек проследити смислену подразумевану вредност или null.
Креирање прилагођеног провајдера је уобичајен образац за капсулирање логике контекста. Унутар таквог провајдера чува се стање (кроз useState или useReducer) и пружа се кроз value проп Provider-а. Ово омогућава сакривање детаља имплементације од компонената потрошача и централизацију логике управљања контекстом на једном месту.
// Прилагођени провајдер са управљањем стањем
const AuthContext = createContext(null);
function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const login = useCallback(async (email, pass) => {
const u = await loginApi(email, pass);
setUser(u);
}, []);
return (
<AuthContext.Provider value={{ user, login }}>
{children}
</AuthContext.Provider>
);
}
У функционалним компонентама, useContext је једини начин да се приступи контексту. Он замењује Consumer компоненту из старог Context API-ја, који је захтевао render-prop образац: <ThemeContext.Consumer>{value => ...}</ThemeContext.Consumer>. useContext чини код линеарнијим и читљивијим, посебно при раду са више контекстата у једној компоненти.
Када користите више контекстата у једној компоненти, једноставно позовите useContext више пута за сваки контекст. Сваки позив враћа вредност одговарајућег Provider-а. Редослед позива није битан, јер је сваки контекст независан ентитет. React оптимизује вишеструке позиве кроз исти fiber систем референци.
function Dashboard() {
const { user } = useContext(AuthContext);
const theme = useContext(ThemeContext);
const { locale } = useContext(I18nContext);
return (
<div className={`dashboard-${theme}`}>
<h1>{locale.greeting}, {user.name}</h1>
</div>
);
}
Избор између useContext-а и Redux-а зависи од обима и сложености управљања стањем. useContext + useReducer је лака замена за Redux за мале и средње апликације. Не захтева инсталацију спољашње библиотеке, лакше је за учење и довољан за већину задатака. Redux је оправдан када је потребна чврста архитектура са middleware, дев алатима и непромељивим ажурирањима.
Главна предност Redux-а над useContext-ом је оптимизација поновних исцртавања. Подразумевано, при промени вредности у Provider-у, сви корисници контекста се поново исцртавају. Redux са useSelector и shallowEqual омогућава компонентама да се претплате на одређене делове стања, што значајно смањује број поновних исцртавања у великим апликацијама. Контекст се такође може оптимизовати поделом на више малих контекстата.
| Критеријум | useContext | Redux |
|---|---|---|
| Сложеност | Нема спољашњих зависности | Захтева подешавање store и middleware |
| Поновна исцртавања | Сви корисници при свакој промени | Само претплаћени на одређени slice |
| DevTools | React DevTools | Redux DevTools са time-travel |
| Middleware | Није подржан | Redux Thunk, Saga, Observable |
| Када изабрати | Средње апликације, 3-5 контекстата | Велике апликације са сложеном пословном логиком |
Према Redux maintainers — When to use Redux (2024), 70% React апликација не потребује Redux. Ако имате мање од 50 компонената и стање нема сложену логику са кеширањем, debounce и споредним ефектима — useContext + useReducer је више него довољан. Redux додаје boilerplate и треба га користити свесно.
Најчешћа грешка је поновно креирање value објекта при сваком исцртавању Provider-а. Ако Provider-у проследите value={{ user, login }}, при сваком исцртавању Provider-а ствара се нови објекат, што изазива поновно исцртавање свих корисника, чак и ако се подаци нису промењили. Решење — мемоизација value-а кроз useMemo или коришћење одвојених контекстата за податке које се често и ретко мењају.
// ❌ Нови објекат при сваком исцртавању — сви корисници се поново исцртавају
<AuthContext.Provider value={{ user, login }}>{children}</AuthContext.Provider>
// ✅ Мемоизована вредност — поновно исцртавање само када се промени корисник или login
const authValue = useMemo(() => ({ user, login }), [user, login]);
<AuthContext.Provider value={authValue}>{children}</AuthContext.Provider>
Да бисте решили проблем „великог контекста”, поделите глобално стање на логичке групе: AuthContext, ThemeContext, I18nContext. Сваки контекст је одговоран за своју област и ажурира се независно. Ово је једноставније него покушај да оптимизујете један гигантски контекст кроз useMemo и пружа предвидљивије понашање поновних исцртавања.
Често постављана питања
Да, ако проследите функцију мутатор у value Provider-а. Типичан образац је чување стања у Provider-у и преношење како података, тако и функција за њихово ажурирање кроз useContext. Потомки компоненти позивају ове функције, и промена стања у Provider-у аутоматски ажурира све кориснике. Ово је основна замена за Redux у малим апликацијама.
За једноставне сценарије, useContext је бржи због непостојања overhead-а од store и middleware. Али код честих ажурирања са великим бројем корисника, Redux побеђује јер његови селектори (useSelector) се претплаћују на одређене делове стања, док useContext поново исцртава све кориснике при свакој промени. За апликације са високом учесталошчу ажурирања (анимације, real-time) избор треба да буде Redux или специјализоване библиотеке.
Не. useContext, као и сви хукови, може бити позван само унутар функционалне React компоненте или прилагођеног хука. Ако вам је потребна вредност контекста у обичној функцији (нпр. у алату или сервису), проследите је као параметар из компоненте или користите одвојени модул са глобалним стањем изван React-а.
Типизација контекста у TypeScript-у је навођење типа у createContext: createContext<AuthContextType | null>(null). Ово гарантује да useContext(AuthContext) враћа вредност исправног типа. Згодан образац је креирање прилагођеног хука useAuth који позива useContext, проверава null и избацује разумљиву грешку: „useAuth must be used within AuthProvider”.
Најчешћи разлог је да се компонента корисник налази изван одговарајућег Provider-а. Проверите да Provider обухвата цело поддрво у којем се користи useContext. Други разлог је прослеђивање Provider-а другом објекту контекста: програмер креира контекст позивом createContext, а користи useContext са другом инстанцом createContext-а.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође