Skip to content

React 19 Hooks — Zero-to-Hero in One Post

Learn every React 19 hook—useActionState, useOptimistic, useTransition, useDeferredValue, useInsertionEffect, use(), and the classics—with copy-paste TypeScript examples.

Published

React 19 keeps every hook from React 18 and adds six more, so you now have 17 built-in hooks at your fingertips.
Below, each hook is grouped by job, explained in one sentence, and paired with a tiny, real-world TypeScript snippet that runs in any Vite, CRA, or Next.js starter.


🧩 1. State Hooks

HookWhy it exists4-line demo
useStateTrack local mutable stateconst [n,setN]=useState(0);
useReducerHandle complex or multi-step stateconst [s,d]=useReducer(reducer,0);
useActionState (NEW)Built-in state machine for forms & server actions[see below]
// useActionState – contact form with loading & success
import { useActionState } from 'react';

async function send(prev: any, fd: FormData) {
  await fetch('/api/contact', { method:'POST', body: fd });
  return { ok: true };
}

export default function Contact() {
  const [msg, submit] = useActionState(send, {});
  return (
    <form action={submit}>
      <input name="email" required />
      <button disabled={msg.ok}>{msg.ok ? 'Sent ✔' : 'Send'}</button>
    </form>
  );
}

📦 2. Ref Hooks

HookWhy it exists4-line demo
useRefHold a mutable box across rendersconst r=useRef(null);
useImperativeHandleLet parent call child methods via ref[see below]
// useImperativeHandle – parent can call .focus()
import { forwardRef, useRef, useImperativeHandle } from 'react';

const FancyInput = forwardRef<HTMLInputElement>((_, ref) => {
  const inner = useRef<HTMLInputElement>(null);
  useImperativeHandle(ref, () => ({ focus: () => inner.current?.focus() }));
  return <input ref={inner} placeholder="Focus me from parent" />;
});

export default function Parent() {
  const ref = useRef<{ focus(): void }>(null);
  return (
    <>
      <FancyInput ref={ref} />
      <button onClick={() => ref.current?.focus()}>Focus</button>
    </>
  );
}

⚡ Effect & Lifecycle Hooks

HookWhy it exists4-line demo
useEffectRun side-effects after paintuseEffect(()=>console.log('mount'),[]);
useLayoutEffectRun synchronously before paintuseLayoutEffect(()=>measure(),[dep]);
useInsertionEffect (NEW)Inject global styles/scripts before paint[see below]
// useInsertionEffect – add CSS-in-JS without FOUC
import { useInsertionEffect } from 'react';

export default function Button({ color }: { color: string }) {
  useInsertionEffect(() => {
    const style = document.createElement('style');
    style.innerHTML = `.btn-${color}{background:${color};}`;
    document.head.append(style);
    return () => style.remove();
  }, [color]);
  return <button className={`btn-${color}`}>Click</button>;
}

🧪 Transition & Defer Hooks

HookWhy it exists4-line demo
useTransitionKeep UI responsive during heavy updates[see below]
useDeferredValueDefer expensive child renders[see below]
// useTransition – switch tab without freezing UI
import { useState, useTransition } from 'react';

export default function Tabs() {
  const [tab, setTab] = useState('home');
  const [pending, start] = useTransition();
  return (
    <>
      <button onClick={() => start(() => setTab('settings'))}>
        Settings
      </button>
      {pending && <span>Loading…</span>}
      {tab === 'settings' && <h2>Settings ⚙️</h2>}
    </>
  );
}
// useDeferredValue – search stays fast while 10 k rows render
import { useState, useDeferredValue, memo } from 'react';

export default function App() {
  const [text, setText] = useState('');
  const deferred = useDeferredValue(text);
  return (
    <>
      <input value={text} onChange={e => setText(e.target.value)} />
      <BigList filter={deferred} />
    </>
  );
}

const BigList = memo(({ filter }: { filter: string }) => (
  <ul>
    {Array.from({ length: 10000 }, (_, i) => `Item ${i}`)
      .filter(it => it.includes(filter))
      .map(it => <li key={it}>{it}</li>)}
  </ul>
));

📝 Form Hooks (NEW)

HookWhy it exists4-line demo
useFormStateCentralised form state[state,action]=useFormState(fn,{});
useFormStatusKnow if any parent form is submitting[see below]
// useFormStatus – reusable SubmitButton
import { useFormStatus } from 'react-dom';

export function SubmitButton() {
  const { pending } = useFormStatus();
  return <button disabled={pending}>{pending ? 'Saving…' : 'Save'}</button>;
}

🎭 Optimistic UI Hook (NEW)

HookWhy it exists4-line demo
useOptimisticShow instant result, roll back on error[see below]
// useOptimistic – like counter with instant +1, rollback on fail
import { useOptimistic, useState } from 'react';

export default function Like({ id, initial }: { id: string; initial: number }) {
  const [likes, setLikes] = useState(initial);
  const [opt, add] = useOptimistic(likes, l => l + 1);

  async function like() {
    add();
    try {
      await fetch(`/api/like/${id}`, { method:'POST' });
      setLikes(l => l + 1);
    } catch { /* auto-rollback */ }
  }

  return <button onClick={like}>{opt} ❤️</button>;
}

🌐 Promise Hook (NEW)

HookWhy it exists4-line demo
useAwait promises inside components[see below]
// use() – fetch without useEffect
import { use } from 'react';

async function getUser(id: string) {
  const res = await fetch(`/api/user/${id}`);
  return res.json();
}

export default function Profile({ id }: { id: string }) {
  const user = use(getUser(id));
  return <h1>Hi {user.name}</h1>;
}

🔄 Memoization Hooks

HookWhy it exists4-line demo
useMemoCache expensive valuesconst m=useMemo(()=>heavy(v),[v]);
useCallbackCache function referencesconst cb=useCallback(fn,[dep]);

🧩 Context Hook

HookWhy it exists4-line demo
useContextConsume context valuesconst theme=useContext(ThemeCtx);

🪝 Debug Hook

HookWhy it exists4-line demo
useDebugValueLabel custom hooks in DevToolsuseDebugValue(Count:${count});

✅ TL;DR

CategoryHooks
StateuseState, useReducer, useActionState
RefuseRef, useImperativeHandle
EffectuseEffect, useLayoutEffect, useInsertionEffect
TransitionuseTransition, useDeferredValue
Form & OptimisticuseFormState, useFormStatus, useOptimistic
Promiseuse
MemoizationuseMemo, useCallback
ContextuseContext
DebuguseDebugValue

React 19 hooksuseActionState exampleuseOptimistic ReactuseTransition tutorialuseDeferredValue guideuseInsertionEffectReact use hookReact 19 form hooksReact 19 best practicesTypeScript React hooks