Overview
Master React hooks with practical examples. Covers useEffect dependencies, stale closures, memoization, and building custom hooks. This guide covers the essential concepts, practical examples, and production-ready patterns you need to get started.
Getting Started
Before diving in, make sure you have the necessary prerequisites installed. This guide assumes basic familiarity with the underlying technology stack.
Core Concepts
Understanding the fundamentals is essential before applying advanced patterns. The following sections break down the key ideas with working code examples.
Best Practices
- Start simple and add complexity only when needed
- Write tests alongside your implementation
- Document decisions that aren't obvious from the code
- Monitor in production with appropriate logging and metrics
Common Pitfalls
Developers commonly run into a few specific issues when first implementing these patterns. Understanding them upfront saves significant debugging time later.
Production Checklist
- Error handling and graceful degradation
- Logging and observability
- Performance testing under realistic load
- Security review
What are React Hooks?
Hooks are functions that let you "hook into" React state and lifecycle features from function components. Introduced in React 16.8, they've become the standard way to write React components.
useState Hook
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const [user, setUser] = useState({ name: '', email: '' });
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
useEffect Hook
import { useState, useEffect } from 'react';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
// Runs on every render
useEffect(() => {
console.log('Component rendered');
});
// Runs only when userId changes
useEffect(() => {
fetchUser(userId).then(setUser);
}, [userId]);
// Cleanup function (componentWillUnmount)
useEffect(() => {
const subscription = subscribe();
return () => subscription.unsubscribe();
}, []);
}
useMemo and useCallback
import { useMemo, useCallback } from 'react';
function ExpensiveComponent({ items, onSelect }) {
// Memoize expensive calculation
const sortedItems = useMemo(() => {
return items.sort((a, b) => a.value - b.value);
}, [items]);
// Memoize function to prevent re-renders
const handleClick = useCallback((id) => {
onSelect(id);
}, [onSelect]);
return sortedItems.map(item => (
<div key={item.id} onClick={() => handleClick(item.id)}>
{item.name}
</div>
));
}
Custom Hooks
function useLocalStorage(key, initialValue) {
const [storedValue, setStoredValue] = useState(() => {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
});
const setValue = (value) => {
setStoredValue(value);
window.localStorage.setItem(key, JSON.stringify(value));
};
return [storedValue, setValue];
}
// Usage
function ThemeToggle() {
const [theme, setTheme] = useLocalStorage('theme', 'light');
return <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>Toggle</button>;
}
Common Mistakes
- Missing dependencies in useEffect
- Using hooks inside conditions or loops
- Over-using useMemo/useCallback (premature optimization)
- Not cleaning up effects (memory leaks)
- Stale closures in callbacks
aiforeverthing.com — JavaScript tools, CSS beautifiers, and more
Frequently Asked Questions
When should I use useMemo?
Only for expensive calculations or to maintain reference equality. Don't wrap everything.
Why do I get "React Hook called conditionally" error?
Hooks must be called in the same order every render. Never call them inside if statements or loops.
aiforeverthing.com — No signup, runs in your browser