state
useState
Declares a piece of local state in a function component and returns the current value along with a setter. Reach for it whenever a component needs to remember a value across renders and re-render when that value changes.
const [state, setState] = useState(initialState) Parameters & Behavior
| Parameter | Purpose |
|---|---|
| initialState | Initial value, or a lazy initializer function called only on first render |
| setState(next) | Replace state with a new value and schedule a re-render |
| setState(prev => next) | Updater form — compute next state from the previous one (safe in batches) |
| Object.is comparison | React bails out of re-render if the new state is Object.is-equal to the current |
Examples
const [count, setCount] = useState(0);
return <button onClick={() => setCount(c => c + 1)}>{count}</button>; Classic counter using the updater form to avoid stale closures
const [user, setUser] = useState(() => JSON.parse(localStorage.getItem('user'))); Lazy initializer — the expensive parse runs only on the first render
const [form, setForm] = useState({ name: '', email: '' });
setForm(f => ({ ...f, name: 'Ada' })); Object state must be replaced immutably — spread the previous value
const [items, setItems] = useState([]);
setItems(prev => [...prev, newItem]); Appending to an array via the updater form is safe across concurrent updates
Gotcha
State updates are asynchronous and batched — reading `count` right after `setCount` still returns the old value. Mutating objects in place will not trigger a re-render; always return a new reference.
Related hooks
useReducer
Manages component state through a reducer function that maps (state, action) to the next state. Reach for it when state transitions are complex, involve multiple sub-values, or when the next state depends on the previous in non-trivial ways.
useRef
Returns a mutable object whose .current property persists for the lifetime of the component without triggering re-renders on change. Reach for it to hold DOM nodes, timers, previous values, or any imperative handle that render output does not depend on.
useEffect
Runs a side effect after the browser has painted the committed render. Reach for it for subscriptions, data fetching, DOM syncing with external systems, timers, and anything that must not block the visual update.
useSyncExternalStore
Subscribes a component to an external store in a way that is safe with concurrent rendering, preventing tearing. Reach for it when writing a library or reading from a store that lives outside React (Redux, Zustand, browser APIs, custom event emitters).