State with useState
Essential useState idioms for local component state without overusing effects.
Busca en todas las páginas de la documentación
Essential useState idioms for local component state without overusing effects.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
useState returns the current value and a setter. Calling the setter schedules a re-render with the next value.
const [count, setCount] = useState(0);
return (
<button type="button" onClick={() => setCount(count + 1)}>
{count}
</button>
);Pass a function when the initial value is expensive to compute. React calls it once on mount, not on every render.
const [data, setData] = useState(() => expensiveParse(raw));When the next state depends on the previous, pass an updater function. This avoids stale closures when updates queue close together.
setCount((c) => c + 1);
setCount((c) => c + 1); // ends +2 from the same click batch baseCopy previous fields with the spread operator. Replace nested objects immutably rather than mutating in place.
setUser((u) => ({ ...u, name: nextName }));Build a new array when adding items. Never push into the existing state array.
setItems((items) => [...items, newItem]);filter returns a new array without the removed id. Keep identity of other items stable.
setItems((items) => items.filter((item) => item.id !== id));map replaces one element and keeps the rest. Match by stable id, not by index, when ids exist.
setItems((items) =>
items.map((item) => (item.id === id ? { ...item, done: true } : item)),
);Flip flags with a functional update so rapid clicks stay correct.
const [open, setOpen] = useState(false);
const toggle = () => setOpen((v) => !v);Prefer several simple useState hooks over one mega-object when fields update independently. Group into one object when fields always change together.
const [query, setQuery] = useState("");
const [page, setPage] = useState(1);Change a key on a component to remount it and re-run all initial state. Ideal for "new form" or "switch entity" flows.
<Editor key={documentId} documentId={documentId} />Controlled inputs store the string (or parsed value) in state and pass it back as value.
const [name, setName] = useState("");
return (
<input value={name} onChange={(e) => setName(e.target.value)} />
);React 19 batches state updates in event handlers and async paths. Multiple setters in one handler usually produce one re-render.
function onSave() {
setStatus("saving");
setError(null);
}If a value can be computed from props or other state during render, compute it - do not mirror it in another useState.
const fullName = `${first} ${last}`;
const visible = items.filter((i) => i.active);Copying a prop into state intentionally "freezes" the initial value. If the prop should win later, either key-reset or fully control from the parent.
const [draft, setDraft] = useState(initialTitle);
// Parent can force reset: <Draft key={version} initialTitle={title} />The setState function identity is stable across renders. Safe to omit from dependency arrays and to pass deeply without wrapping in useCallback.
useEffect(() => {
const id = setInterval(() => setTicks((t) => t + 1), 1000);
return () => clearInterval(id);
}, []); // setTicks is stableStack versions: React 19 · TypeScript (strict) · concurrent rendering defaults
Revisado por Chris St. John·Última actualización: 18 jul 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥