State is data that changes over time and, when updated, causes React to re-render the component. The useState hook is the primary way to add state to a function component.
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0); // [value, setter] pair
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
Rules of state
- Never mutate state directly (
count++on its own does nothing useful) — always call the setter function. - State updates are asynchronous and batched; React groups multiple
setStatecalls in the same event handler into a single re-render. - Each component instance has its own independent state.
Functional updates
When the new state depends on the previous state, pass a function to the setter instead of a value — this avoids bugs with stale state, especially with batching:
// risky if count changes multiple times before re-render
setCount(count + 1);
// safe: always uses the latest state
setCount(prev => prev + 1);
State with objects and arrays
Because React compares state by reference, always create a new object/array instead of mutating the existing one:
const [user, setUser] = useState({ name: 'Rahim', age: 20 });
// wrong — mutates existing object, React won't detect the change
user.age = 21;
// correct — spread the old object, override what changed
setUser(prev => ({ ...prev, age: 21 }));
const [items, setItems] = useState(['a', 'b']);
setItems(prev => [...prev, 'c']); // add
setItems(prev => prev.filter(i => i !== 'a')); // remove
Handling events
React wraps native DOM events in a cross-browser SyntheticEvent. Handlers are passed as functions, not strings, and use camelCase:
function LoginForm() {
const [email, setEmail] = useState('');
function handleSubmit(e) {
e.preventDefault(); // stop the default full-page reload
console.log('Submitting:', email);
}
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<button type="submit">Log in</button>
</form>
);
}
Common event props: onClick, onChange, onSubmit, onMouseEnter, onKeyDown, onFocus, onBlur.