webroad.online
  1. 1Web
  2. 2HTML
  3. 3CSS
  4. 4JavaScript
  5. 5TypeScript
  6. 6Git
  7. 7Unelte
  8. 8React
  9. 9State management
  10. 10Next.js
  11. 11Formulare
  12. 12Date și backend
  13. 13SEO
  14. 14Tailwind CSS
  15. 15Animații
  16. 16Testare
  17. 17Arhitectură
React · Lecția 4 din 7

Hook-uri custom

Logică reutilizabilă, regulile hook-urilor, useSyncExternalStore.

Actualizat

Ce este un hook

Un hook e o funcție specială React (numele începe cu use) care îi dă unei componente acces la funcționalități React: memorie (useState), efecte (useEffect), context (useContext) etc.

Un hook custom e o funcție scrisă de tine care folosește alte hook-uri — așa extragi logică cu state și o refolosești în mai multe componente.

function useToggle(initial = false) {
  const [on, setOn] = useState(initial)
  const toggle = useCallback(() => setOn(v => !v), [])
  return [on, toggle] as const
}

const [menuOpen, toggleMenu] = useToggle()
const [darkMode, toggleDark] = useToggle(true)   // state complet separat

Important: un hook custom partajează logica, nu state-ul. Fiecare componentă care îl apelează are propria copie.

Regulile hook-urilor

  1. Apelezi hook-uri doar la nivelul de sus al unei componente sau al unui alt hook — nu în if, bucle sau callback-uri.
  2. Doar din componente React sau din alte hook-uri — nu din funcții obișnuite.

De ce: React identifică hook-urile după ordinea apelurilor la fiecare randare. Un if care sare peste un hook amestecă ordinea și state-ul ajunge la hook-ul greșit.

Hook-urile React — pe categorii

Categorie Hook-uri Pentru
state useState, useReducer memoria componentei
context useContext, use(Context) date partajate fără props
efecte useEffect, useLayoutEffect sincronizare cu exteriorul
referințe useRef DOM și valori fără re-randare
performanță useMemo, useCallback memoizare (React Compiler le face automat)
surse externe useSyncExternalStore abonare la store-uri, media queries, localStorage
acțiuni (React 19) useActionState, useOptimistic, useFormStatus, useTransition formulare, mutații, UI optimist
date async use(promise) citești un Promise cu Suspense

Exemple care merită în orice proiect

function useDebouncedValue<T>(value: T, delay = 300) {
  const [debounced, setDebounced] = useState(value)
  useEffect(() => {
    const id = setTimeout(() => setDebounced(value), delay)
    return () => clearTimeout(id)
  }, [value, delay])
  return debounced
}

function useMediaQuery(query: string) {
  return useSyncExternalStore(
    cb => {
      const m = matchMedia(query)
      m.addEventListener('change', cb)
      return () => m.removeEventListener('change', cb)
    },
    () => matchMedia(query).matches,
    () => false,                       // valoarea pe server
  )
}

useSyncExternalStore e modul corect de a te abona la o sursă externă — exact cum detectează editorul de cod din aplicația asta tema light/dark.

Când extragi un hook custom

Semn Exemplu
aceeași combinație useState + useEffect în 2+ componente debounce, fetch, media query
o componentă are multă logică și puțin JSX useCheckout() scoate logica, componenta rămâne doar UI
vrei să testezi logica separat hook-ul se testează cu renderHook

Nu extrage hook-uri „pentru că se poate” — un hook folosit o singură dată, cu 3 linii, doar ascunde codul.

Unde stau în FSD

Hook legat de o entitate → entities/<x>/model/use-x.ts. Hook generic (debounce, media query) → shared/lib/.

Pe scurt

  • Hook custom = funcție use... care compune alte hook-uri; partajează logica, nu state-ul.
  • Doar la nivelul de sus, mereu în aceeași ordine.
  • useSyncExternalStore pentru surse externe; extrage hook-uri când logica se repetă.

Surse oficiale

Exerciții

Ți-a fost utilă pagina?

Un click — fără cont.