React Guide
React useState Hook
The most important React hook. Master it once, use it everywhere.
Quick answer: useState returns an array with two values: the current state and a setter function. Declare it with const [value, setValue] = useState(initial). Call the setter to update state and trigger a re-render. Use the functional form setValue(prev => prev + 1) when the new state depends on the old one.
Basic Syntax
Import useState and declare it inside your component:
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
The array destructuring syntax gives you the value and the setter in one line.
State Types
useState accepts any JavaScript value — strings, numbers, booleans, objects, and arrays:
const [name, setName] = useState('Alice'); // string
const [age, setAge] = useState(25); // number
const [isActive, setIsActive] = useState(false); // boolean
const [user, setUser] = useState({ name: '' }); // object
const [items, setItems] = useState([]); // array
Updating Objects & Arrays
Never mutate state directly. Always create a new copy:
// ❌ Wrong — mutates state
user.name = 'Bob';
setUser(user);
// ✅ Correct — creates a new object
setUser({ ...user, name: 'Bob' });
// ❌ Wrong — mutates array
items.push(newItem);
setItems(items);
// ✅ Correct — creates a new array
setItems([...items, newItem]);
Rule: React compares references, not values. If you mutate the same object, React will not detect the change and won't re-render.
Functional Updates
When your new state depends on the old state, use a function:
// ❌ Might be stale
setCount(count + 1);
setCount(count + 1);
// Result: 1 increment, not 2
// ✅ Always uses latest state
setCount(prev => prev + 1);
setCount(prev => prev + 1);
// Result: 2 increments
💡 Why this matters: React batches state updates. If you call setCount(count + 1) twice, both use the same stale count value. The functional form ensures each update uses the latest state.
Multiple useState Calls
You can use useState as many times as you need in one component:
function Form() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [age, setAge] = useState(0);
const [agree, setAgree] = useState(false);
// Each state is independent
}
For complex forms or tightly-related state, consider grouping them into a single object or using useReducer.
Lazy Initial State
If computing the initial state is expensive, pass a function:
// ❌ Runs on every render
const [data, setData] = useState(expensiveCompute());
// ✅ Runs only once
const [data, setData] = useState(() => expensiveCompute());
Useful when reading from localStorage, parsing large JSON, or performing heavy calculations.
🛡️ Common Mistakes
- Mutating state directly: Always create new objects or arrays.
- Reading state right after setting: State updates are async — the value will be stale in the same render.
- Skipping functional updates: When the new state depends on the old one, use the callback form.
- Calling useState conditionally: Hooks must be called at the top level, never inside loops, conditions, or nested functions.
- Using state for derived values: If a value can be computed from existing state or props, don't store it — compute it.
❓ Frequently Asked Questions
What does useState do in React?
useState is a React Hook that lets you add state to functional components. It returns an array with the current state value and a function to update it.
Can I use multiple useState calls?
Yes. You can call useState multiple times in the same component. Each call is independent and manages its own piece of state.
Why is my useState update not working?
State updates are asynchronous. If your new state depends on the old state, use the functional form: setCount(prev => prev + 1). Also, never mutate objects or arrays directly — always create new copies.
When should I use useState vs useReducer?
Use useState for simple, independent values. Use useReducer when state logic is complex, involves multiple sub-values, or when the next state depends heavily on the previous one.
Does updating useState re-render the component?
Yes. Calling the setter function triggers a re-render of the component. React batches multiple updates for performance.