useContext — je React hook, který poskytuje funkcionálním komponentám přímý přístup k datům z kontextu vytvořeného prostřednictvím createContext. Kontext v Reactu řeší problém props drilling — předávání props přes mnoho zprostředkujících komponent, které samy tato data nepoužívají. Podle React Documentation (2025), useContext přijímá objekt kontextu a vrací aktuální hodnotu nastavenou nejbližším Providerem výše ve stromu komponent. Když se hodnota v Provideru změní, všechny komponenty používající useContext se automaticky znovu vykreslí.
Hlavní
useContext — je hook přidaný v React 16.8 společně s ostatními hooks, který umožňuje číst hodnotu z React kontextu. Kontext je vestavěný mechanismus v Reactu, určený k předávání dat stromem komponent bez nutnosti ručního předávání props na každé úrovni. useContext nahrazuje Consumer komponentu ze starého Context API a dělá kód konciznějším a čitelnějším.
Typické scénáře použití kontextu zahrnují motivy vzhledu (světlý/tmavý), regionální nastavení a překlady (i18n), autentizaci uživatele, nastavení aplikace a jakákoli jiná globální data, která potřebuje mnoho komponent na různých úrovních vnoření. Tým React doporučuje používat kontext pro data, která jsou globální pro podstrom komponent, ale ne pro celou aplikaci.
Podle React Team — Context documentation (2025) je nesprávné použití kontextu jednou z hlavních příčin výkonnostních problémů v React aplikacích. Každá změna hodnoty v Provideru způsobí překreslení všech spotřebitelů, bez ohledu na to, která část dat se změnila. Optimalizace pomocí useMemo a rozdělení kontextů tento problém řeší.
import { createContext, useContext } from 'react';
// Vytvořit kontext s výchozí hodnotou
const ThemeContext = createContext('světlý');
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button className={`btn-${theme}`}>Click</button>;
}
Mechanismus kontextu v Reactu je implementován prostřednictvím vzoru Provider-Consumer. createContext vrací objekt se dvěma entitami: Provider — komponenta, která předává hodnotu, a samotný objekt kontextu používaný v useContext. Provider se montuje do stromu komponent a předává hodnotu všem potomkům bez ohledu na hloubku vnoření.
Když React narazí na volání useContext, pohybuje se nahoru fiber stromem při hledání nejbližšího Provideru pro daný kontext. Pokud je Provider nalezen, vrátí se jeho hodnota. Pokud Provider nalezen není, vrátí se výchozí hodnota předaná do createContext. Toto vyhledávání probíhá při každém vykreslení, ale díky memorizaci fiber uzlů je velmi rychlé a neovlivňuje výkon.
Podle React — Context internals (2024), interní implementace useContext používá propojený seznam hooků, podobně jako useState. Každý hook uchovává odkaz na fiber uzel, což umožňuje Reactu rychle určit, který Provider odpovídá danému kontextu. Pokud Provider aktualizuje hodnotu, React označí všechny fiber uzly používající tento kontext k překreslení.
Provider komponenty lze vkládat do sebe a vytvářet tak hierarchii kontextů. Každý dětský Provider přepisuje hodnotu rodiče pro svůj podstrom. To je užitečné, když je na jedné obrazovce potřeba světlé téma a ve vnořeném modálním okně — tmavé. useContext vždy vrací hodnotu nejbližšího Provideru výše ve stromu.
const UserContext = createContext(null);
const ThemeContext = createContext('světlý');
function App() {
return (
<UserContext.Provider value={{ name: 'Alice' }}>
<ThemeContext.Provider value='dark'>
<Profile />
</ThemeContext.Provider>
</UserContext.Provider>
);
}
Funkce createContext(defaultValue) vytváří objekt kontextu. Parametr defaultValue se používá, když komponenta zavolá useContext, ale výše ve stromu není odpovídající Provider. Bez defaultValue vrátí useContext undefined, což může vést k neočekávaným chybám. Doporučuje se vždy předávat smysluplnou výchozí hodnotu nebo null.
Vytvoření vlastního provideru je běžný vzor pro zapouzdření logiky kontextu. Uvnitř takového provideru je uložen stav (přes useState nebo useReducer) a poskytován prostřednictvím value prop Provideru. To umožňuje skrýt detaily implementace před spotřebitelskými komponentami a centralizovat logiku správy kontextu na jednom místě.
// Vlastní provider se správou stavu
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>
);
}
Ve funkcionálních komponentách je useContext jediným způsobem, jak získat přístup ke kontextu. Nahrazuje Consumer komponentu ze starého Context API, který vyžadoval vzor render-prop: <ThemeContext.Consumer>{value => ...}</ThemeContext.Consumer>. useContext dělá kód lineárnějším a čitelnějším, zejména při práci s více kontexty v jedné komponentě.
Při použití více kontextů v jedné komponentě jednoduše zavolejte useContext několikrát pro každý kontext. Každé volání vrátí hodnotu odpovídajícího Provideru. Pořadí volání není důležité, protože každý kontext je nezávislá entita. React optimalizuje násobná volání prostřednictvím stejného systému fiber odkazů.
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>
);
}
Výběr mezi useContext a Redux závisí na měřítku a složitosti správy stavu. useContext + useReducer je lehká náhrada Redux pro malé a střední aplikace. Nevyžaduje instalaci externí knihovny, je snadnější na naučení a dostatečný pro většinu úkolů. Redux je oprávněný, když je vyžadována striktní architektura s middleware, vývojářskými nástroji a neměnnými aktualizacemi.
Hlavní výhoda Reduxu oproti useContext je optimalizace překreslování. Ve výchozím nastavení při změně hodnoty v Provideru se všichni spotřebitelé kontextu překreslí. Redux s useSelector a shallowEqual umožňuje komponentám odebírat se pouze na určité části stavu, což výrazně snižuje počet překreslení ve velkých aplikacích. Kontext lze také optimalizovat rozdělením na mnoho malých kontextů.
| Kritérium | useContext | Redux |
|---|---|---|
| Složitost | Žádné externí závislosti | Vyžaduje konfiguraci store a middleware |
| Překreslení | Všichni spotřebitelé při každé změně | Pouze odebírající konkrétní slice |
| DevTools | React DevTools | Redux DevTools s time-travel |
| Middleware | Není podporován | Redux Thunk, Saga, Observable |
| Kdy vybrat | Střední aplikace, 3-5 kontextů | Velké aplikace se složitou business logikou |
Podle Redux maintainers — When to use Redux (2024) 70% React aplikací Redux nepotřebuje. Pokud máte méně než 50 komponent a stav nemá složitou logiku s cacheováním, debounce a vedlejšími účinky — useContext + useReducer je více než dostatečný. Redux přidává boilerplate a měl by být používán vědomě.
Nejčastější chybou je znovuvytváření objektu value při každém vykreslení Provideru. Pokud předáváte do Provideru value={{ user, login }}, při každém vykreslení Provideru vzniká nový objekt, což způsobí překreslení všech spotřebitelů, i když se data nezměnila. Řešení — memorizace value pomocí useMemo nebo použití samostatných kontextů pro často a zřídka se měnící data.
// ❌ Nový objekt při každém vykreslení — všichni spotřebitelé se překreslí
<AuthContext.Provider value={{ user, login }}>{children}</AuthContext.Provider>
// ✅ Memorizovaná hodnota — překreslení pouze když se změní uživatel nebo login
const authValue = useMemo(() => ({ user, login }), [user, login]);
<AuthContext.Provider value={authValue}>{children}</AuthContext.Provider>
K vyřešení problému „velkého kontextu” rozdělte globální stav do logických skupin: AuthContext, ThemeContext, I18nContext. Každý kontext odpovídá za svou doménu a aktualizuje se nezávisle. To je jednodušší než se snažit optimalizovat jeden gigantický kontext pomocí useMemo a poskytuje předvídatelnější chování překreslování.
Často kladené otázky
Ano, pokud předáte mutační funkci do value Provideru. Typickým vzorem je uložení stavu v Provideru a předávání jak dat, tak funkcí pro jejich aktualizaci prostřednictvím useContext. Dětské komponenty volají tyto funkce a změna stavu v Provideru automaticky aktualizuje všechny spotřebitele. To je základní náhrada Redux pro malé aplikace.
Pro jednoduché scénáře je useContext rychlejší díky absenci režie store a middleware. Ale při častých aktualizacích s velkým počtem spotřebitelů Redux vítězí, protože jeho selektory (useSelector) odebírají konkrétní části stavu, zatímco useContext překresluje všechny spotřebitele při každé změně. Pro aplikace s vysokou frekvencí aktualizací (animace, real-time) by měla být volba Redux nebo specializované knihovny.
Ne. useContext, stejně jako všechny hooks, lze volat pouze uvnitř funkcionální React komponenty nebo vlastního hooku. Pokud potřebujete získat hodnotu kontextu v běžné funkci (např. v utilitě nebo službě), předejte ji jako parametr z komponenty nebo použijte samostatný modul s globálním stavem mimo React.
Typování kontextu v TypeScriptu — určení typu v createContext: createContext<AuthContextType | null>(null). To zaručuje, že useContext(AuthContext) vrací hodnotu správného typu. Pohodlným vzorem je vytvoření vlastního hooku useAuth, který volá useContext, kontroluje null a vyvolá srozumitelnou chybu: „useAuth must be used within AuthProvider”.
Nejčastějším důvodem je, že spotřebitelská komponenta se nachází mimo odpovídající Provider. Zkontrolujte, zda Provider obaluje celý podstrom, ve kterém se useContext používá. Druhým důvodem je předání Provideru jinému objektu kontextu: vývojář vytváří kontext voláním createContext, ale používá useContext s jinou instancí createContext.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také