useState: co to je, hook stavu a syntax v Reactu

Autor: IT Sectr Publikováno: 2026-07-04 Doba čtení: 9 min

useState — je vestavěný React hook, který umožňuje funkcionálním komponentám spravovat lokální stav bez převodu na třídové komponenty. React 16.8 představil hooks a useState se stal nejpoužívanějším z nich, nahrazující this.state a this.setState z třídového přístupu. Podle React Documentation (2025) používá více než 80% komponent v moderních React aplikacích useState pro správu dat formulářů, příznaků rozhraní a čítačů. Hook vrací n-tici složenou z aktuální hodnoty a setter funkce, která aktualizuje stav a iniciuje překreslení komponenty.

Hlavní body

  • useState — hook pro správu lokálního stavu ve funkcionálních React komponentách.
  • N-tice — vrací pár [hodnota, setter], kde setter je funkce aktualizující stav.
  • Překreslení — volání setteru vždy iniciuje překreslení komponenty s novou hodnotou.
  • Typy dat — useState pracuje s čísly, řetězci, poli, objekty a booleovskými hodnotami.
  • Neměnnost — stav nelze mutovat přímo, pouze přes setter funkci.

Co je useState v Reactu

useState — je základní React hook, přidaný ve verzi 16.8, který dává funkcionálním komponentám možnost ukládat a měnit lokální stav. Před příchodem hooks bylo možné stav používat pouze v třídových komponentách přes this.state a this.setState, což činilo funkcionální komponenty výhradně prezentačními. useState toto omezení odstranil a umožnil psát celou aplikaci na funkcionálních komponentách.

Hook přijímá jeden argument — počáteční hodnotu stavu — a vrací pole o dvou prvcích. První prvek je aktuální hodnota stavu, druhý je funkce pro jeho aktualizaci. React garantuje, že setter funkce je stabilní a nemění se mezi vykresleními, což umožňuje bezpečné předávání do podřízených komponent a použití v uzávěrech.

Podle React DevTools Usage Survey (2024) je useState používán v 96% React aplikací, což z něj dělá nejrozšířenější hook v ekosystému. Dokonce i v aplikacích používajících globální stav přes Redux nebo Zustand zůstává lokální stav přes useState hlavním mechanismem správy UI stavu — otevřené modály, hodnoty vstupních polí, aktivní karty.

jsx
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>
    );
}

Jak funguje useState

Vnitřní mechanismus useState je založen na systému fiber uzlů Reactu. Každá komponenta v Reactu je reprezentována fiber uzlem, který ukládá související seznam hooks ve formě propojeného seznamu. Když komponenta zavolá useState, React vytvoří nový uzel v tomto seznamu a uloží do něj aktuální hodnotu stavu a odkaz na frontu aktualizací.

Při volání setter funkce React neaktualizuje stav okamžitě. Místo toho umístí aktualizaci do fronty (pending state queue), naplánuje překreslení komponenty a teprve během dalšího vykreslení vypočítá nový stav na základě starého a aplikovaných aktualizací. To zajišťuje dávkové zpracování — pokud v jednom handleru události zavoláte setter třikrát, React je seskupí do jednoho překreslení.

Podle React Team — React 18 Working Group (2024) bylo automatické dávkové zpracování rozšířeno v React 18: nyní jsou aktualizace stavu seskupovány nejen v handlerech událostí, ale také v setTimeout, Promise callbackách a nativních handlerech. To přineslo zvýšení výkonu až o 30% ve scénářích s vícenásobnými aktualizacemi stavu.

Funkcionální aktualizace stavu

Když nový stav závisí na předchozím, použijte funkcionální formu setteru: setCount(prev => prev + 1). React předá funkci aktuální hodnotu stavu v okamžiku aplikace aktualizace, což zaručuje správnost i při dávkových aktualizacích. Bez funkcionální formy může setCount(count + 1) použít zastaralou hodnotu, pokud je voláno několikrát za sebou.

jsx
// Líná inicializace — spouští se pouze jednou
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)

Syntaxe useState: deklarace a aktualizace

Základní syntaxe useState je velmi stručná: const [state, setState] = useState(initialValue). Počáteční hodnota se používá pouze při prvním vykreslení; při následujících vykresleních ji React ignoruje a vrací aktuální uloženou hodnotu. Pokud počáteční výpočet vyžaduje nákladné operace, předejte inicializační funkci: useState(() => computeExpensiveInitial()).

Líná inicializace (lazy initial state) je obzvláště důležitá, když počáteční hodnota pochází z localStorage, složité transformace dat nebo parsování URL parametrů. React volá inicializační funkci pouze jednou — při připojení komponenty, což šetří zdroje při následujících vykresleních. Bez líné inicializace bude nákladný výraz vyhodnocen při každém vykreslení, i když je jeho výsledek ignorován.

FormaPříkladKdy použít
PřímáuseState(0)Jednoduchá počáteční hodnota
LínáuseState(() => compute())Nákladný počáteční výpočet
Funkcionální settersetState(prev => prev + 1)Aktualizace na základě předchozí
Přímý settersetState(newValue)Nová hodnota nezávisí na staré
jsx
// Stav objektu — vytvořte novou referenci
const [user, setUser] = useState(() => {
    const saved = localStorage.getItem('user');
    return saved ? JSON.parse(saved) : null;
});

useState s různými typy dat

useState funguje stejně dobře s primitivy (čísla, řetězce, booleany) a referenčními typy (pole, objekty). Existuje však důležitý rozdíl: u primitiv React detekuje změnu podle hodnoty, u objektů a polí — podle reference. Mutace existujícího objektu bez vytvoření nového nezpůsobí překreslení, protože reference zůstala stejná.

Při práci s objekty a poli vždy vytvářejte novou kopii se změněnými daty. Pro objekty použijte spread syntaxi: setUser(prev => ({...prev, name: newName})). Pro pole — metody vracející nové pole: filter, map, concat, nebo spread syntaxi pro přidávání prvků. Mutační metody jako push, pop, splice přímo nebudou fungovat — React je ignoruje, protože reference na pole se nezměnila.

jsx
// ✅ Správně: hooks na nejvyšší úrovni
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]);

Pravidla používání hooks s useState

Stejně jako všechny React hooks, useState podléhá dvěma pravidlům. Za prvé: volejte hooks pouze na nejvyšší úrovni komponenty — nelze je umístit do podmínek, cyklů nebo vnořených funkcí. To zaručuje, že hooks jsou volány ve stejném pořadí při každém vykreslení, což je kritické pro vnitřní propojený seznam Reactu.

Druhé pravidlo: volejte hooks pouze z funkcionálních React komponent nebo vlastních hooks. Nevolejte useState z běžných funkcí, callbacků nebo třídových komponent. Porušení těchto pravidel vede k chybě Invalid hook call, kterou React zachycuje ve fázi provádění.

  • Ne v podmínkách — if (flag) { useState(0) } narušuje pořadí volání hooks.
  • Ne v cyklech — for (...) { useState(0) } činí pořadí nepředvídatelným.
  • Ne v callbackách — useEffect(() => { useState(0) }, []) rozbije propojený seznam.
jsx
// ❌ Problém zastaralého uzávěru
function GoodComponent() {
    const [count, setCount] = useState(0);
    const [name, setName] = useState('');
    // ✅ Opraveno funkcionální aktualizací
}

// čítač je zastaralý!
function BadComponent() {
    if (isLogged) {
        const [user, setUser] = useState(null);
    }
}

Typické chyby s useState

Nejčastější chyba — přímá mutace objektů a polí místo vytváření nových referencí. Vývojáři si zvykli na mutabilní styl z třídových komponent, kde this.state.user.name = „Nové jméno“ fungovalo (ačkoli také nebylo doporučeno). Ve funkcionálních komponentách je taková mutace jednoduše ignorována: React nevidí změnu reference a komponentu nepřekresluje.

  • Mutace objektu — user.name = „Nové“ místo setUser({...user, name: „Nové“}).
  • Zastaralý uzávěr — použití zastaralé hodnoty v setteru bez funkcionální formy.
  • Zbytečná překreslení — volání setteru se stejnou hodnotou (React 18 pro primitiva stejně vykreslí).
  • Resetování stavu — neúmyslná aktualizace key prop komponenty, která ji znovu připojí.

Problém zastaralého uzávěru (stale closure) nastává, když callback předaný do useEffect nebo handleru události „zachytí“ zastaralou hodnotu stavu z uzávěru v okamžiku vytvoření callbacku. Řešení — použijte funkcionální formu setteru nebo zahrňte potřebné hodnoty do pole závislostí useEffect. Podle React Documentation — Hooks FAQ (2025) jsou zastaralé uzávěry druhou nejčastější příčinou chyb v hooks po nesprávném poli závislostí.

jsx
// ❌ 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);
}, []);

Často kladené otázky

Lze použít useState pro složité vnořené objekty?

Ano, ale s opatrností. Pro hluboce vnořené objekty vyžaduje každá úroveň kopírování při aktualizaci: setState(prev => ({...prev, nested: {...prev.nested, key: newValue}})). Pokud máte objekty se třemi nebo více úrovněmi vnoření, zvažte Immer (knihovna pro neměnitelné aktualizace) nebo rozdělte stav na několik useState pro různé úrovně.

Je useState asynchronní nebo synchronní?

useState je asynchronní v tom smyslu, že volání setteru neaktualizuje hodnotu okamžitě. React umístí aktualizaci do fronty a provede ji při příštím vykreslení. Po setCount(newValue) proměnná count v aktuální funkci stále obsahuje starou hodnotu. Nová hodnota bude k dispozici až při příštím volání komponenty. Mechanismus dávkování zaručuje, že vícenásobná volání jsou seskupena do jednoho vykreslení.

Co se stane, když se useState zavolá mimo komponentu?

React vyvolá chybu Invalid hook call. Hooks mohou být volány pouze uvnitř funkcionálních React komponent nebo vlastních hooks (funkcí, jejichž název začíná na use). Toto omezení je zabudováno do implementace hooks: používají fiber strom komponenty k ukládání stavu a mimo komponentu tento strom není k dispozici.

Kdy použít useState a kdy useReducer?

useState je vhodný pro jednoduché nezávislé stavy (čítače, vstupní pole, příznaky). useReducer je lepší, když je stav složitý objekt s několika poli, logika aktualizace závisí na typu akce nebo další stav vyžaduje složitou transformaci. Praktické pravidlo: pokud máte více než tři související pole stavu — použijte useReducer.

Proč useState neaktualizuje hodnotu okamžitě?

To je provedeno pro výkon. Pokud by useState aktualizoval stav synchronně, každé volání setteru by způsobilo okamžité překreslení, což by vedlo k vícenásobným překreslením uvnitř jednoho handleru události. Dávkové zpracování, při kterém React seskupuje aktualizace a provádí jedno překreslení, je optimalizace zavedená již v React 16 a výrazně vylepšená v React 18 s automatickým dávkovým zpracováním.

Shrnutí

  • useState — základní React hook pro správu lokálního stavu ve funkcionálních komponentách, vracející [state, setter].
  • Neměnnost — stav nelze mutovat přímo; vždy předejte novou hodnotu nebo použijte funkcionální formu setteru.
  • Líná inicializace — pro nákladné počáteční výpočty předejte funkci: useState(() => compute()).
  • Funkcionální setter — setState(prev => prev + 1) zaručuje správnost při dávkových aktualizacích.
  • Dávkové zpracování — React seskupuje vícenásobná volání setteru do jednoho překreslení pro optimalizaci.
  • Pravidla hooks — volejte useState pouze na nejvyšší úrovni komponenty, ne v podmínkách nebo cyklech.
  • Typy dat — u objektů a polí vždy vytvářejte novou referenci při aktualizaci.

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í.

Prodiskutovat projekt

Přečtěte si také