useState Hook
useState Hook
The useState hook lets you add state to functional components.
Basic Usage
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
How useState Works
useState(0)initializes state with 0- Returns
[count, setCount]:count: current state valuesetCount: function to update state
- Calling
setCounttriggers re-render
Multiple State Variables
function Form() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [age, setAge] = useState(0);
return (
<form>
<input value={name} onChange={(e) => setName(e.target.value)} />
<input value={email} onChange={(e) => setEmail(e.target.value)} />
<input type="number" value={age} onChange={(e) => setAge(Number(e.target.value))} />
</form>
);
}
State with Objects
function UserForm() {
const [user, setUser] = useState({
name: "",
email: "",
age: 0
});
// Update single property
const updateName = (name) => {
setUser({ ...user, name });
};
return (
<form>
<input value={user.name} onChange={(e) => updateName(e.target.value)} />
</form>
);
}
State Updates
State Updates
State Updates are Asynchronous
function Counter() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
console.log(count); // Still 0! Not updated yet
};
return (
<div>
<p>{count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
}
State Batching
function Form() {
const [name, setName] = useState("");
const [age, setAge] = useState(0);
const handleSubmit = () => {
// These are batched into one re-render
setName("Alice");
setAge(30);
};
}
Functional Updates
When new state depends on old state, use a function:
function Counter() {
const [count, setCount] = useState(0);
// Bad: may use stale value
const increment = () => {
setCount(count + 1);
setCount(count + 1); // Only adds 1!
};
// Good: always uses latest value
const increment = () => {
setCount(prev => prev + 1);
setCount(prev => prev + 1); // Adds 2!
};
}
Immutable State
Immutable State
Why Immutable?
React uses reference equality to detect changes. Mutating objects won't trigger re-renders.
// Wrong: mutation
function TodoApp() {
const [todos, setTodos] = useState([{ text: "Learn React", done: false }]);
const toggle = (index) => {
todos[index].done = true; // Mutation!
setTodos(todos); // No re-render!
};
}
// Correct: immutable update
const toggle = (index) => {
const newTodos = todos.map((todo, i) =>
i === index ? { ...todo, done: true } : todo
);
setTodos(newTodos); // Triggers re-render
};
Immutable Patterns
// Adding to array
setTodos([...todos, newTodo]);
// Removing from array
setTodos(todos.filter(t => t.id !== id));
// Updating item in array
setTodos(todos.map(t => t.id === id ? { ...t, done: true } : t));
// Updating object property
setUser({ ...user, name: "New Name" });
// Removing property
const { password, ...rest } = user;
setUser(rest);
spread Operator
// Shallow copy object
const newUser = { ...user, name: "Alice" };
// Shallow copy array
const newTodos = [...todos, newTodo];
// Nested updates (not recommended - use libraries)
const newState = {
...state,
user: {
...state.user,
name: "Alice"
}
};
Practice Problems
Create a reusable React component implementing State. Include proper state management and accessibility.
Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where neededWrite unit and integration tests for State using React Testing Library.
Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility testsOptimize State for performance. Consider memoization, code splitting, and bundle size.
Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysisQuiz
1. What does useState return?
2. Are state updates synchronous?
3. Why should state be immutable?
4. When should you use functional updates?
Flashcards
Question
What does useState do?
Click to reveal answer
Answer
Adds state to functional components
Question
What does useState return?
Click to reveal answer
Answer
An array with [state, setState]
Question
Why use functional updates?
Click to reveal answer
Answer
When new state depends on previous state
Question
What is immutable state?
Click to reveal answer
Answer
Creating new objects instead of mutating existing ones
Question
What is State?
Click to reveal answer
Answer
State is a key concept in frontend development.
Revision Notes
Key Takeaways
- 1.useState adds state to functional components
- 2.State updates are asynchronous and batched
- 3.Use functional updates when new state depends on old
- 4.State must be immutable for React to detect changes
- 5.Use spread operator for immutable updates
Interview Tips
- •Explain why state updates are asynchronous
- •Show immutable state update patterns
- •Demonstrate when to use functional updates
Cheat Sheet
Cheat Sheet
Basic useState
const [count, setCount] = useState(0);
setCount(count + 1);
Functional Update
setCount(prev => prev + 1);
Immutable Patterns
// Add
setTodos([...todos, newTodo]);
// Remove
setTodos(todos.filter(t => t.id !== id));
// Update
setTodos(todos.map(t => t.id === id ? {...t, done: true} : t));
// Object
setUser({ ...user, name: "Alice" });