useContext: суштина, хук приступа контексту и провајдери у React-у

Аутор: IT Sectr Објављено: 2026-07-04 Време читања: 9 мин

useContext — је Реакт хук који функционалним компонентама пружа директан приступ подацима из контекста креираног кроз createContext. Контекст у React-у решава проблем props drilling — преношење props-а кроз више посредних компонената који сами не користе ове податке. Према React Documentation (2025), useContext прихвата објекат контекста и враћа тренутну вредност постављену од најближег Provider-а изнад у дрвету компонената. Када се вредност у Provider-у промени, сви компоненти који користе useContext се аутоматски поново исцртавају.

Главно

  • useContext — хук за читање вредности из React контекста без props drilling-а.
  • createContext — креира објекат контекста са подразумеваном вредношћу и Provider компонентом.
  • Provider — компонента омотач која преноси вредност контекста свим потомцима.
  • Поновно исцртавање — промена вредности у Provider-у изазива поновно исцртавање свих потрошача контекста.
  • Прескакање посредних компонената — useContext омогућава преношење података кроз више нивоа угњежђења.

Шта је useContext у React-у

useContext — је хук додат у React 16.8 заједно са осталим хуковима, који омогућава читање вредности из React контекста. Контекст је уграђени механизам у React-у, намењен за преношење података кроз дрво компонената без потребе за ручним преношењем props-а на сваком нивоу. useContext замењује Consumer компоненту из старог Context API-ја и чини код концизнијим и читљивијим.

Типични сценарији коришћења контекста укључују теме изгледа (светла/тамна), локалне поставке и преводе (i18n), аутентификацију корисника, поставке апликације и све друге глобалне податке који су потребни бројним компонентима на различитим нивоима угњежђења. React тим препоручује коришћење контекста за податке које су глобалне за поддрво компонената, али не за целу апликацију.

Према React Team — Context documentation (2025), неправилно коришћење контекста је један од главних узрока проблема са перформансама у React апликацијама. Свака промена вредности у Provider-у изазива поновно исцртавање свих корисника, без обзира на то који део података се променио. Оптимизација кроз useMemo и подела контекста решава овај проблем.

jsx
import { createContext, useContext } from 'react';

// Креирај контекст са подразумеваном вредношћу
const ThemeContext = createContext('светло');

function ThemedButton() {
    const theme = useContext(ThemeContext);
    return <button className={`btn-${theme}`}>Click</button>;
}

Како ради контекст у React-у

Механизам контекста у 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 компоненте се могу угњездивати једна у другу, стварајући хијерархију контекста. Сваки потомак Provider-а прегаза вредност родитеља за своје поддрво. Ово је корисно када је на једном екрану потребна светла тема, а у угњежденом модалном прозору — тамна. useContext увек враћа вредност најближег Provider-а изнад у дрвету.

jsx
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

Функција createContext(defaultValue) креира објекат контекста. Параметар defaultValue се користи када компонента позове useContext, али изнад у дрвету нема одговарајућег Provider-а. Без defaultValue, useContext ће вратити undefined, што може довести до неочекиваних грешака. Препоручује се увек проследити смислену подразумевану вредност или null.

Креирање прилагођеног провајдера је уобичајен образац за капсулирање логике контекста. Унутар таквог провајдера чува се стање (кроз useState или useReducer) и пружа се кроз value проп Provider-а. Ово омогућава сакривање детаља имплементације од компонената потрошача и централизацију логике управљања контекстом на једном месту.

jsx
// Прилагођени провајдер са управљањем стањем
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-а у потомким компонентама

У функционалним компонентама, useContext је једини начин да се приступи контексту. Он замењује Consumer компоненту из старог Context API-ја, који је захтевао render-prop образац: <ThemeContext.Consumer>{value => ...}</ThemeContext.Consumer>. useContext чини код линеарнијим и читљивијим, посебно при раду са више контекстата у једној компоненти.

Када користите више контекстата у једној компоненти, једноставно позовите useContext више пута за сваки контекст. Сваки позив враћа вредност одговарајућег Provider-а. Редослед позива није битан, јер је сваки контекст независан ентитет. React оптимизује вишеструке позиве кроз исти fiber систем референци.

jsx
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-а и Redux-а зависи од обима и сложености управљања стањем. useContext + useReducer је лака замена за Redux за мале и средње апликације. Не захтева инсталацију спољашње библиотеке, лакше је за учење и довољан за већину задатака. Redux је оправдан када је потребна чврста архитектура са middleware, дев алатима и непромељивим ажурирањима.

Главна предност Redux-а над useContext-ом је оптимизација поновних исцртавања. Подразумевано, при промени вредности у Provider-у, сви корисници контекста се поново исцртавају. Redux са useSelector и shallowEqual омогућава компонентама да се претплате на одређене делове стања, што значајно смањује број поновних исцртавања у великим апликацијама. Контекст се такође може оптимизовати поделом на више малих контекстата.

КритеријумuseContextRedux
СложеностНема спољашњих зависностиЗахтева подешавање store и middleware
Поновна исцртавањаСви корисници при свакој промениСамо претплаћени на одређени slice
DevToolsReact DevToolsRedux 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 и треба га користити свесно.

Типичне грешке са useContext

Најчешћа грешка је поновно креирање value објекта при сваком исцртавању Provider-а. Ако Provider-у проследите value={{ user, login }}, при сваком исцртавању Provider-а ствара се нови објекат, што изазива поновно исцртавање свих корисника, чак и ако се подаци нису промењили. Решење — мемоизација value-а кроз useMemo или коришћење одвојених контекстата за податке које се често и ретко мењају.

  • Непотребна поновна исцртавања — нови value објекат при сваком исцртавању Provider-а. Користите useMemo за мемоизацију value-а.
  • Превелики контекст — један Provider са десетинама поља призива поновно исцртавање свих потомака при промени било којег поља. Поделите на више контекстата према значењу.
  • Недостатак defaultValue — ако Provider није пронађен, useContext враћа defaultValue, а ако је undefined — сваки позив ће пасти са TypeError.
  • Угњежђени Provider истог типа — прегазање контекста на дубоким нивоима може збунити и довести до неочекиваних вредности.
jsx
// ❌ Нови објекат при сваком исцртавању — сви корисници се поново исцртавају
<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 или Redux?

За једноставне сценарије, useContext је бржи због непостојања overhead-а од store и middleware. Али код честих ажурирања са великим бројем корисника, Redux побеђује јер његови селектори (useSelector) се претплаћују на одређене делове стања, док useContext поново исцртава све кориснике при свакој промени. За апликације са високом учесталошчу ажурирања (анимације, real-time) избор треба да буде Redux или специјализоване библиотеке.

Могу ли да користим useContext изван React компоненте?

Не. useContext, као и сви хукови, може бити позван само унутар функционалне React компоненте или прилагођеног хука. Ако вам је потребна вредност контекста у обичној функцији (нпр. у алату или сервису), проследите је као параметар из компоненте или користите одвојени модул са глобалним стањем изван React-а.

Како useContext ради са TypeScript-ом?

Типизација контекста у TypeScript-у је навођење типа у createContext: createContext<AuthContextType | null>(null). Ово гарантује да useContext(AuthContext) враћа вредност исправног типа. Згодан образац је креирање прилагођеног хука useAuth који позива useContext, проверава null и избацује разумљиву грешку: „useAuth must be used within AuthProvider”.

Зашто useContext враћа undefined иако Provider постоји?

Најчешћи разлог је да се компонента корисник налази изван одговарајућег Provider-а. Проверите да Provider обухвата цело поддрво у којем се користи useContext. Други разлог је прослеђивање Provider-а другом објекту контекста: програмер креира контекст позивом createContext, а користи useContext са другом инстанцом createContext-а.

Резиме

  • useContext — хук за читање вредности из React контекста, који елиминише потребу за props drilling-ом.
  • createContext — креира објекат контекста са Provider-ом за преношење података и defaultValue за случај без Provider-а.
  • Мемоизација value-а — користите useMemo за value у Provider-у да бисте избегли непотребних поновних исцртавања корисника.
  • Подела контекстата — поделите глобално стање на више малих контекстата према логичким групама.
  • Хијерархија Provider-а — могу се угњездити Provider истог типа за прегазање вредности у делу дрвета.
  • useContext + useReducer — лака замена за Redux за средње апликације без спољашњих зависности.
  • Не замењује Redux — за сложену логику са middleware-ом и честим ажурирањима бирајте Redux са селекторима.

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође