useState Hook
useState is the hook that gives a function component memory between renders. const [count, setCount] = useState(0); First paint uses 0. setCount(1) queues a re-render. The next paint, count is 1. Without useState, a plain let count = 0 would reset to 0 on every render and the button would never climb.
The initial argument runs on the first paint only. If creating the initial value is expensive (big table), pass a function: useState(() => buildRows()). That function runs once. Passing buildRows() with parentheses would run every render — wasted work.
Rules you must recite: only call useState at the top of the function, not inside if, loops, or nested functions. Same order every render. Don’t call it in a class. React matches hook calls by order, not by name. Break the order, get a red error.
Functional updater: setCount(c => c + 1) reads the latest queued value. If you write setCount(count + 1) twice in one click, both reads see 0, result is 1. With c => c + 1 twice, result is 2. Use the updater when the next value depends on the previous one, especially in fast clicks or inside effects.
Let’s walk a Like button. const [liked, setLiked] = useState(false); return <button onClick={() => setLiked(!liked)}>{liked ? 'Liked' : 'Like'}</button>. First screen: Like. Click → Liked. Click again → Like. That is the whole hook for a fresher viva.
Trap: useState inside if (user). Trap: logging count immediately after setCount. Trap: putting a new object as initial every time without the lazy function. Trap: using useState for a value that should not paint (timer id) — that is useRef.
useState Hook — on screen — Like. Click → Liked. useState(false) is the first paint only.
useState(false)
│ click
▼
setLiked(true)
│
▼
Like → LikedReturn pair + one click example + hook rules.