useState gives a function component a piece of local, reactive state. It returns a pair: the current value and a setter function. Calling the setter schedules a re-render with the new value.
[count, setCount] = ();
(count + );
( c + );
useState gives a function component a piece of local, reactive state. It returns a pair: the current value and a setter function. Calling the setter schedules a re-render with the new value.
[count, setCount] = ();
(count + );
( c + );
1. Updates are asynchronous / batched. count does not change on the line after setCount; it has the new value on the next render. So this only increments once:
setCount(count + 1);
setCount(count + 1); // both read the SAME stale `count` → +1 total
Use the functional updater when the next value depends on the previous one, because React passes the latest value in:
setCount(c => c + 1);
setCount(c => c + 1); // +2 total — each gets the up-to-date value
2. The initial value is used only on the first render. For an expensive default, pass a function so it runs once (lazy init):
const [data] = useState(() => expensiveInit()); // runs once, not every render
State is what makes a component interactive — React re-runs the function and re-renders the UI whenever state changes.
Treat state as immutable: create a new array/object instead of mutating, e.g. setItems([...items, x]), otherwise React may not detect the change.