React Háčky — co to je, základní háčky a pravidla používání

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

React Hooks (háčky) — jsou funkce, které umožňují používat stav, efekty, kontext a další možnosti Reactu ve funkčních komponentách, bez psaní tříd. Představené v React 16.8, háčky radikálně změnily přístup k vývoji a nahradily složité vzory jako HOC a render props. Podle React, 2024 existuje 15 vestavěných háčků pokrývajících všechny scénáře správy komponent.

Hlavní

  • Háčky — funkce pro připojení možností Reactu k funkčním komponentám bez extends Component.
  • useState — základní háček pro správu stavu, vrací hodnotu a setter.
  • useEffect — pro vedlejší efekty: API požadavky, odběry, časovače, manipulace s DOM.
  • useContext — pro přístup ke kontextu Reactu bez obalů Consumer a static contextType.
  • Pravidla háčků — volat pouze na nejvyšší úrovni a pouze uvnitř funkčních komponent nebo vlastních háčků.

Co jsou React háčky?

React Hooks (háčky) — sada vestavěných funkcí v Reactu, které umožňují ‘připojení’ k vnitřním mechanismům frameworku bez vytváření tříd. Před React 16.8 mohly funkční komponenty pouze přijímat props a vracet JSX — jakákoli složitá logika vyžadovala třídní komponentu.

Problém třídních komponent — oddělení související logiky. Kód týkající se jedné entity (například odběr WebSocket) byl nuceně rozdělen mezi componentDidMount, componentDidUpdate a componentWillUnmount. Háčky to řeší: veškerá logika se seskupí do jednoho useEffect.

Druhý problém — znovupoužití logiky. Pro znovupoužití stavové logiky mezi třídními komponentami bylo nutné použít HOC (komponenty vyššího řádu) nebo render props — oba vzory vytvářely další vnoření ve stromu komponent. Vlastní háčky řeší tento problém bez vnoření.

useState — správa stavu

useState — nejzákladnější háček. Přijímá počáteční hodnotu a vrací tuple: aktuální hodnotu a funkci pro její aktualizaci. Na rozdíl od this.setState ve třídách, useState neslučuje objekty — nový stav zcela nahrazuje předchozí pro konkrétní volání useState.

js
import React, { useState } from 'react';

function Form() {
  const [text, setText] = useState('');
  const [submitting, setSubmitting] = useState(false);

  async function handleSubmit() {
    setSubmitting(true);
    await fetch('/api/submit', {
      method: 'POST',
      body: JSON.stringify({ text })
    });
    setSubmitting(false);
  }

  return (
    <div>
      <input
        value={text}
        onChange={e => setText(e.target.value)}
      />
      <button onClick={handleSubmit}
        disabled={submitting}>
        {submitting ? 'Saving...' : 'Submit'}
      </button>
    </div>
  );
}

Funkční forma setState

Setter useState může přijmout funkci, která obdrží předchozí hodnotu a vrátí novou. Funkční forma je povinná, když se nový stav počítá z předchozího a jsou možné dávková volání setState — každé volání obdrží aktuální předchozí hodnotu.

useEffect — vedlejší efekty a životní cyklus

useEffect — háček pro provádění vedlejších efektů ve funkčních komponentách. Přijímá dva argumenty: funkci-efekt a pole závislostí. React spouští efekt po každém renderu, ale při zadání závislostí — pouze když se některá z nich změní.

Prázdné pole závislostí [] znamená, že se efekt spustí jednou po prvním renderu (analogie componentDidMount). Návrat funkce z efektu je cleanup, který se spustí při odpojení (analogie componentWillUnmount) a před opětovným spuštěním efektu.

js
import React, { useState, useEffect } from 'react';

function ChatRoom({ roomId }) {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    const socket = new WebSocket(`wss://chat/${roomId}`);

    socket.onmessage = (event) => {
      setMessages(prev => [...prev, JSON.parse(event.data)]);
    };

    // Cleanup - zavřít socket
    return () => socket.close();
  }, [roomId]);

  return <ul>
    {messages.map((msg, i) =>
      <li key={i}>{msg.text}</li>
    )}
  </ul>;
}

Závislosti useEffect — jsou jediným spojením mezi efektem a vnějším světem. Pokud je v efektu použita proměnná z props nebo stavu, musí být v poli závislostí. Ignorování tohoto pravidla je zdrojem chyb se zastaralými daty (stale closure).

useContext — přístup ke kontextu

useContext — háček pro čtení hodnoty kontextu. Přijímá objekt kontextu vytvořený pomocí React.createContext a vrací aktuální hodnotu. Pokud se kontext změní, komponenta se automaticky přerenderuje s novou hodnotou.

Před příchodem useContext vyžadoval přístup ke kontextu ve funkčních komponentách obalení v Context.Consumer, což vytvářelo vnoření. useContext zcela eliminuje Consumer — stačí zavolat háček na libovolném místě funkční komponenty.

js
import React, { createContext, useContext } from 'react';

const ThemeContext = createContext('světlý');

function ThemedButton() {
  const theme = useContext(ThemeContext);

  return <button
    className={`btn btn-${theme}`}
  >
    {theme === 'dark' ? 'moon' : '☀️'}
  </button>;
}

useContext není náhradou za Redux nebo globální stav. React doporučuje používat kontext pro zřídka měnící se hodnoty — téma, jazyk, autorizace. Pro často aktualizovaná data každý re-render přepočítá všechny spotřebitele kontextu, což může snížit výkon.

useReducer — složitá logika stavu

useReducer — alternativa k useState pro stavy se složitou logikou aktualizace. Přijímá funkci reducer a počáteční stav, vrací aktuální stav a funkci dispatch. Reducer obdrží aktuální stav a akci, vrátí nový stav — čistá funkce bez vedlejších efektů.

useReducer je užitečný zejména když několik akcí (set, reset, increment, addItem) spravuje jeden stav. Místo několika useState s různými settery — jeden reducer s jasnými typy akcí. To činí logiku předvídatelnou a snadno testovatelnou.

js
import React, { useReducer } from 'react';

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { ...state, count: state.count + 1 };
    case 'setStep':
      return { ...state, step: action.step };
    case 'reset':
      return { count: 0, step: 1 };
    default:
      throw new Error('Unknown action: ' + action.type);
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, {
    count: 0,
    step: 1
  });

  return (
    <>
      <p>Count: {state.count}</p>
      <button
        onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button
        onClick={() => dispatch({ type: 'reset' })}>Reset</button>
    </>
  );
}

useRef, useMemo, useCallback — optimalizace

useRef vytváří měnitelný objekt, který přetrvává mezi rendery. Změna current nezpůsobuje re-render. Hlavní použití — přístup k DOM prvkům a ukládání mutovatelných hodnot (časovače, předchozí hodnoty, instance knihoven).

useMemo memoizuje výsledek funkce. Přepočítává hodnotu pouze když se změní jedna ze závislostí. Používejte pro nákladné výpočty — filtrování velkých polí, řazení, formátování dat. useCallback — speciální případ useMemo pro memoizaci funkcí.

js
import React, { useRef, useMemo, useCallback } from 'react';

function SearchPage({ items, query, onItemSelect }) {
  const inputRef = useRef(null);

  // Autofocus při připojení
  useEffect(() => {
    inputRef.current?.focus();
  }, []);

  // Memoizovat filtrovaný výsledek
  const filtered = useMemo(() => {
    return items.filter(item =>
      item.name.toLowerCase()
        .includes(query.toLowerCase())
    );
  }, [items, query]);

  // Memoizovat callback
  const handleSelect = useCallback((id) => {
    onItemSelect(id);
  }, [onItemSelect]);

  return (
    <div>
      <input ref={inputRef}
        value={query}
        onChange={e => setQuery(e.target.value)}
      />
      <ul>
        {filtered.map(item =>
          <li key={item.id}>
            <button
              onClick={() => handleSelect(item.id)}>
              {item.name}
            </button>
          </li>
        )}
      </ul>
    </div>
  );
}

Důležité pravidlo: useRef, useMemo a useCallback — nástroje optimalizace, nikoli povinné konstrukce. Neobalujte vše do useMemo — nejprve změřte výkon. Předčasná optimalizace komplikuje kód. React renderuje komponenty rychle; useMemo je potřeba pouze když jsou výpočty skutečně nákladné (O(n²) a výše).

Pravidla háčků a časté chyby

React zavedl dvě přísná pravidla pro háčky. První: volejte háčky pouze na nejvyšší úrovni — ne uvnitř podmínek, cyklů nebo vnořených funkcí. Druhé: volejte háčky pouze z React funkčních komponent nebo vlastních háčků. ESLint plugin eslint-plugin-react-hooks automaticky kontroluje obě pravidla.

Nejčastější chyba — porušení pořadí volání háčků. React spoléhá na pořadí volání háčků mezi rendery. Pokud je háček uvnitř podmínky a nebyl zavolán v jednom z renderů, všechny následující háčky se posunou a způsobí chyby.

ChybaCo se dějeŘešení
Háček v podmíncePořadí háčků se lámePřesuňte logiku podmínky dovnitř háčku
Stale closureEfekt používá starou hodnotuPřidejte všechny závislosti do pole
Nekonečná smyčkauseEffect bez závislostí mění stavUrčete závislosti nebo použijte useReducer
Změna ref v renderuVedlejší efekt v těle funkcePřesuňte mutace do useEffect

Druhá častá chyba — stale closure v useEffect. Pokud je v efektu použita proměnná neuvedená v závislostech, efekt ‘zachytí’ její hodnotu v okamžiku vytvoření uzávěru. Řešení — vždy zahrňte všechny použité proměnné do pole závislostí. Pokud je závislostí příliš mnoho, rozdělte efekt na několik částí.

Často kladené otázky

Proč nelze háčky volat v podmínkách?

React spoléhá na pořadí volání háčků mezi rendery. Pokud je háček zavolán v podmínce a nefungoval v jednom z renderů, všechny následující háčky ‘kloužou’ — jejich stav se promíchá. Pravidlo ESLint hooks/exhaustive-deps na to upozorňuje.

Jaký je rozdíl mezi useEffect a useLayoutEffect?

useLayoutEffect je synchronní a provádí se před tím, než prohlížeč vykreslí změny. useEffect je asynchronní — po vykreslení. Používejte useLayoutEffect pouze když potřebujete změřit nebo změnit DOM dříve, než uživatel uvidí změny (pozice popover, obnovení posouvání).

Jak zrušit fetch požadavek při odpojení?

Použijte AbortController uvnitř useEffect. Vytvořte controller, předejte signal do fetch a v cleanup funkci zavolejte controller.abort(). Pro staré prohlížeče postačí příznak cancelled: return () => { cancelled = true; } s kontrolou před setState.

Co je vlastní háček a kdy ho vytvořit?

Vlastní háček — JavaScriptová funkce s předponou use, která používá vestavěné háčky. Vytvořte ho, když se stejná logika s háčky opakuje ve dvou nebo více komponentách. Příklady: useDebounce, useLocalStorage, useMediaQuery. Vlastní háčky nahrazují HOC a render props.

Proč se useEffect spouští dvakrát v Strict Mode?

V Strict Mode React záměrně připojí a odpojí komponentu dvakrát ve vývojovém režimu, aby našel chyby s nevyčištěnými efekty. Pokud je cleanup napsán správně, dvojité volání nezpůsobuje problémy. V produkčním režimu k tomu nedochází.

Shrnutí

  • React Hooks (háčky) — funkce pro použití stavu, efektů a kontextu ve funkčních komponentách, které nahradily třídy.
  • useState — základní háček pro lokální stav s funkčním setterem pro bezpečné aktualizace.
  • useEffect — univerzální háček pro vedlejší efekty s polem závislostí a cleanup funkcí.
  • useContext — přímý přístup ke kontextu Reactu bez obalů Consumer a dalšího vnoření.
  • useReducer — pro složitou logiku stavu s typy akcí, alternativa Reduxu v rámci jedné komponenty.
  • useRef, useMemo, useCallback — nástroje optimalizace: DOM reference, memoizace hodnot a callbacků.
  • Pravidlo nejvyšší úrovně — přísné omezení volání háčků mimo podmínky, cykly a vnořené funkce.

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é