Mastering React Hooks
Deep dive into React Hooks including useState, useEffect, useContext, and custom hooks for building powerful components.

Mastering React Hooks
A deep dive into React Hooks including useState, useEffect, and custom hooks for managing complex state.
useState Deep Dive
// Simple state
const [count, setCount] = useState(0)
// State with initializer function (for expensive computations)
const [data, setData] = useState(() => {
return computeExpensiveValue()
})
// Updating based on previous state
setCount(prev => prev + 1)
// Object state (always spread to avoid losing properties)
const [form, setForm] = useState({ name: '', email: '' })
setForm(prev => ({ ...prev, name: 'Ahmed' }))
useEffect Best Practices
// β
Data fetching with cleanup
useEffect(() => {
const controller = new AbortController()
async function fetchData() {
try {
const res = await fetch('/api/data', { signal: controller.signal })
const json = await res.json()
setData(json)
} catch (err) {
if (err.name !== 'AbortError') {
setError(err)
}
}
}
fetchData()
return () => controller.abort()
}, [])
// β
Event listener with cleanup
useEffect(() => {
function handleResize() {
setWidth(window.innerWidth)
}
window.addEventListener('resize', handleResize)
return () => window.removeEventListener('resize', handleResize)
}, [])
Custom Hooks
// useLocalStorage
function useLocalStorage<T>(key: string, initialValue: T) {
const [value, setValue] = useState<T>(() => {
const stored = localStorage.getItem(key)
return stored ? JSON.parse(stored) : initialValue
})
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value))
}, [key, value])
return [value, setValue] as const
}
// useDebounce
function useDebounce<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState(value)
useEffect(() => {
const timer = setTimeout(() => setDebouncedValue(value), delay)
return () => clearTimeout(timer)
}, [value, delay])
return debouncedValue
}
useReducer for Complex State
type Action =
| { type: 'ADD_ITEM'; payload: Item }
| { type: 'REMOVE_ITEM'; payload: string }
| { type: 'TOGGLE_ITEM'; payload: string }
function cartReducer(state: CartState, action: Action): CartState {
switch (action.type) {
case 'ADD_ITEM':
return { ...state, items: [...state.items, action.payload] }
case 'REMOVE_ITEM':
return { ...state, items: state.items.filter(i => i.id !== action.payload) }
case 'TOGGLE_ITEM':
return {
...state,
items: state.items.map(i =>
i.id === action.payload ? { ...i, selected: !i.selected } : i
),
}
}
}
const [state, dispatch] = useReducer(cartReducer, { items: [] })
Conclusion
Hooks make React components more powerful and easier to reason about. Master useState and useEffect, build custom hooks to encapsulate reusable logic, and use useReducer for complex state management. These patterns will make your React code cleaner and more maintainable.
Share this article
Subscribe to our newsletter
Get the latest articles, tutorials, and insights delivered straight to your inbox. No spam, unsubscribe anytime.
Related Articles

Modern CSS Techniques for 2024
Explore the latest CSS features including container queries, cascade layers, and advanced grid layouts.
Read more
Getting Started with Next.js 15
Learn about the latest features in Next.js 15 including async components, improved performance, and new routing capabilities.
Read more
Authentication Best Practices
Implement secure authentication with JWT, OAuth, and modern security patterns for web applications.
Read more