
React Hooks
About this quiz
This quiz about React Hooks features 10 questions. It was generated by one of our users February 12, 2026.
React Hooks: Revolutionizing Function Components
React Hooks fundamentally transformed how developers write React applications when they were introduced in version 16.8. Before Hooks, function components were considered "stateless" and could only render UI based on props, while class components held the monopoly on state management and lifecycle methods. Hooks shattered this limitation by allowing function components to "hook into" React's powerful features like state, context, and side effects. This paradigm shift not only simplified component logic but also made code more reusable, testable, and easier to understand.
The beauty of Hooks lies in their elegant simplicity and composability. Built-in hooks like useState bring stateful logic to function components, while useEffect handles side effects and replaces multiple lifecycle methods with a single, intuitive API. useContext makes consuming context data effortless, and useReducer provides a Redux-like state management pattern for complex scenarios. Beyond the built-in options, developers can create custom hooks to encapsulate and share stateful logic across components, promoting the DRY (Don't Repeat Yourself) principle like never before.
Today, Hooks have become the preferred approach for React development, with many considering them essential knowledge for any React developer. They've enabled cleaner component hierarchies, reduced boilerplate code, and made React applications more performant through better optimization opportunities. Ready to test your understanding of this game-changing feature?
React Hooks: Complete Study Guide ๐ฃ
Table of Contents
- Introduction to React Hooks
- Core Hook Concepts
- State Management with useState
- Side Effects with useEffect
- Context with useContext
- Performance Optimization
- Advanced State Management
- Hook Rules and Best Practices
- Practice Examples
Introduction to React Hooks
What is the Primary Purpose of React Hooks? ๐ฏ
React Hooks were introduced in React 16.8 to solve several fundamental problems:
**Primary Purposes:**
Enable State in Functional Components
// Before Hooks (Class Component) class Counter extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } render() { return <div>{this.state.count}</div>; } } // After Hooks (Functional Component) function Counter() { const [count, setCount] = useState(0); return <div>{count}</div>; }Reuse Stateful Logic Between Components
// Custom Hook for reusable logic function useCounter(initialValue = 0) { const [count, setCount] = useState(initialValue); const increment = () => setCount(count + 1); const decrement = () => setCount(count - 1); return { count, increment, decrement }; } // Use in multiple components function ComponentA() { const { count, increment } = useCounter(10); return <button onClick={increment}>{count}</button>; }Simplify Component Logic
- Eliminate complex lifecycle methods
- Reduce component hierarchy
- Make code more readable and maintainable
Better Developer Experience
- Easier testing
- Better code splitting
- Improved performance optimizations
Core Hook Concepts
The Rules of Hooks ๐
โ ๏ธ Critical: Hooks must follow these rules to work correctly!
- Only call Hooks at the top level
- Only call Hooks from React functions
State Management with useState
Which Hook is Used to Manage State in a Functional Component? ๐
The useState hook is the primary hook for managing state in functional components.
**Basic Syntax:**
const [state, setState] = useState(initialValue);
**Examples:**
import React, { useState } from 'react';
function UserProfile() {
// String state
const [name, setName] = useState('');
// Number state
const [age, setAge] = useState(0);
// Boolean state
const [isActive, setIsActive] = useState(false);
// Object state
const [user, setUser] = useState({
email: '',
preferences: {}
});
// Array state
const [items, setItems] = useState([]);
return (
<div>
<input
value={name}
onChange={(e) => setName(e.target.value)}
/>
<button onClick={() => setAge(age + 1)}>
Age: {age}
</button>
</div>
);
}
What is the Correct Way to Update State When the New State Depends on the Previous State? ๐
When updating state based on the previous state, always use the functional update pattern:
**โ Correct Way:**
function Counter() {
const [count, setCount] = useState(0);
// Functional update - CORRECT
const increment = () => {
setCount(prevCount => prevCount + 1);
};
// Multiple updates work correctly
const incrementTwice = () => {
setCount(prevCount => prevCount + 1);
setCount(prevCount => prevCount + 1); // This works!
};
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>+1</button>
<button onClick={incrementTwice}>+2</button>
</div>
);
}
**โ Incorrect Way:**
function Counter() {
const [count, setCount] = useState(0);
// Direct reference - PROBLEMATIC
const increment = () => {
setCount(count + 1); // May use stale state
};
// Multiple updates won't work as expected
const incrementTwice = () => {
setCount(count + 1);
setCount(count + 1); // Both use same 'count' value!
};
}
**Complex State Updates:**
function ShoppingCart() {
const [cart, setCart] = useState([]);
const addItem = (newItem) => {
setCart(prevCart => [...prevCart, newItem]);
};
const updateQuantity = (id, quantity) => {
setCart(prevCart =>
prevCart.map(item =>
item.id === id
? { ...item, quantity }
: item
)
);
};
const removeItem = (id) => {
setCart(prevCart =>
prevCart.filter(item => item.id !== id)
);
};
}
Side Effects with useEffect
When Does the useEffect Hook Run by Default? โฐ
By default, useEffect runs after every render (both initial render and updates).
function MyComponent() {
const [count, setCount] = useState(0);
// Runs after every render
useEffect(() => {
console.log('Component rendered!');
document.title = `Count: ${count}`;
});
return (
<button onClick={() => setCount(count + 1)}>
{count}
</button>
);
}
What Does an Empty Dependency Array [] in useEffect Indicate? ๐ฏ
An empty dependency array [] means the effect runs only once after the initial render (similar to componentDidMount).
function DataFetcher() {
const [data, setData] = useState(null);
// Runs only once after initial render
useEffect(() => {
async function fetchData() {
const response = await fetch('/api/data');
const result = await response.json();
setData(result);
}
fetchData();
}, []); // Empty dependency array
return <div>{data ? data.title : 'Loading...'}</div>;
}
**useEffect Patterns:**
function EffectExamples() {
const [count, setCount] = useState(0);
const [name, setName] = useState('');
// 1. No dependency array - runs after every render
useEffect(() => {
console.log('After every render');
});
// 2. Empty dependency array - runs once
useEffect(() => {
console.log('Only on mount');
}, []);
// 3. Specific dependencies - runs when dependencies change
useEffect(() => {
console.log('When count changes');
}, [count]);
// 4. Multiple dependencies
useEffect(() => {
console.log('When count or name changes');
}, [count, name]);
}
What is the Purpose of the Cleanup Function in useEffect? ๐งน
The cleanup function prevents memory leaks and unwanted side effects by cleaning up subscriptions, timers, and event listeners.
**Basic Cleanup Pattern:**
useEffect(() => {
// Setup
const subscription = someAPI.subscribe();
// Cleanup function
return () => {
subscription.unsubscribe();
};
}, []);
**Real-world Examples:**
function TimerComponent() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
// Setup timer
const interval = setInterval(() => {
setSeconds(prev => prev + 1);
}, 1000);
// Cleanup timer
return () => {
clearInterval(interval);
};
}, []);
return <div>Seconds: {seconds}</div>;
}
function WindowSizeTracker() {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight
});
useEffect(() => {
// Setup event listener
function handleResize() {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight
});
}
window.addEventListener('resize', handleResize);
// Cleanup event listener
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
return <div>{windowSize.width} x {windowSize.height}</div>;
}
function WebSocketComponent() {
const [messages, setMessages] = useState([]);
useEffect(() => {
// Setup WebSocket connection
const ws = new WebSocket('wss://example.com/socket');
ws.onmessage = (event) => {
setMessages(prev => [...prev, event.data]);
};
// Cleanup WebSocket connection
return () => {
ws.close();
};
}, []);
return (
<ul>
{messages.map((msg, index) => (
<li key={index}>{msg}</li>
))}
</ul>
);
}
Context with useContext
Which Hook Would You Use to Access a React Context Value? ๐
The useContext hook is used to access React context values in functional components.
**Setting Up Context:**
// 1. Create Context
const ThemeContext = React.createContext();
const UserContext = React.createContext();
// 2. Create Provider Component
function App() {
const [theme, setTheme] = useState('light');
const [user, setUser] = useState(null);
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<UserContext.Provider value={{ user, setUser }}>
<Header />
<MainContent />
</UserContext.Provider>
</ThemeContext.Provider>
);
}