5 React Hooks Mistakes I Made So You Don't Have To
Common React Hooks pitfalls and how to avoid them. Learn from my mistakes and save yourself hours of debugging.
I’ve been using React Hooks since they were released, and I’ve made every mistake in the book. Here are the big ones so you can learn from my pain.
Mistake 1: Forgetting Dependencies
// 🚫 Wrong
useEffect(() => {
fetchUser(userId);
}, []); // userId is missing!
// ✅ Right
useEffect(() => {
fetchUser(userId);
}, [userId]);
The empty dependency array means “run once on mount.” But if userId changes, your effect won’t re-run and your UI will be stale.
Pro tip: Enable the eslint-plugin-react-hooks rule. It’ll yell at you about missing dependencies.
Mistake 2: Using State for Everything
Not everything needs to be state:
// 🚫 Wrong - Derived state
const [users, setUsers] = useState([]);
const [activeUsers, setActiveUsers] = useState([]);
useEffect(() => {
setActiveUsers(users.filter(u => u.active));
}, [users]);
// ✅ Right - Compute it
const [users, setUsers] = useState([]);
const activeUsers = users.filter(u => u.active);
If you can calculate it from existing state, just calculate it. No need to store it separately.
Mistake 3: Infinite Loops from Hell
// 🚫 Wrong - Creates infinite loop
const [count, setCount] = useState(0);
useEffect(() => {
setCount(count + 1); // This triggers re-render, which runs effect...
}); // No dependency array = runs every render!
// ✅ Right - Only run once
useEffect(() => {
setCount(c => c + 1);
}, []); // Empty array = only on mount
I’ve crashed more browsers this way than I’d like to admit.
Mistake 4: Async Functions in useEffect
// 🚫 Wrong
useEffect(async () => {
const data = await fetchData();
setData(data);
}, []);
// ✅ Right
useEffect(() => {
async function loadData() {
const data = await fetchData();
setData(data);
}
loadData();
}, []);
// ✅ Even Better - Handle cleanup
useEffect(() => {
let cancelled = false;
async function loadData() {
const data = await fetchData();
if (!cancelled) {
setData(data);
}
}
loadData();
return () => {
cancelled = true;
};
}, []);
useEffect expects a cleanup function, not a Promise. Async functions return Promises.
Mistake 5: Creating Functions Inside Dependencies
// 🚫 Wrong - New function every render
useEffect(() => {
handleData();
}, [handleData]); // handleData is recreated every render!
// ✅ Right - Wrap in useCallback
const handleData = useCallback(() => {
// ... do stuff
}, [/* dependencies */]);
useEffect(() => {
handleData();
}, [handleData]);
Or better yet, just put the function inside the effect if it’s only used there.
Bonus Mistake: Overusing useCallback/useMemo
// 🚫 Probably unnecessary
const memoizedValue = useMemo(() => {
return 2 + 2;
}, []);
// ✅ Just do it
const value = 2 + 2;
Only use useMemo and useCallback when you have a proven performance problem. They’re not freethey add complexity and memory overhead.
When to actually use them:
- Heavy computations
- Preventing child re-renders (with React.memo)
- Dependencies of other hooks
The Mental Model
Think of hooks as:
useState- A variable that persists between rendersuseEffect- “After this renders, do this thing”useCallback- “Remember this function”useMemo- “Remember this computed value”
Debugging Tools
- React DevTools - See component renders in real-time
- Why Did You Render - Library to detect unnecessary renders
- useWhyDidYouUpdate - Custom hook to log what changed
Conclusion
Hooks are powerful but not magic. They’re just JavaScript functions with rules. Learn the rules, use the linter, and you’ll avoid 90% of the headaches.
And if you do hit an infinite loop, don’t panic. Just check your dependencies and make sure you’re not creating new objects/functions every render.
We’ve all been there. 😅
Happy hooking! 🪝
Keep reading
Why I'm Using Moondream Instead of Cloud Vision APIs
Moondream vs GPT Vision vs Gemini: local vision AI that runs on your laptop. Free image captioning, OCR, object detection, and visual Q&A without API costs. Includes Python examples and GitHub repo.
Computer Vision
Maybe LLM CLI Is All You Need.
Boost developer productivity with command-line AI tools. Learn Simon Willison's LLM CLI, build custom translation tools, and automate git commits. Practical examples for terminal-based AI workflows.
Developer Tools
LLM Data Extraction: A Complete Guide to Document Processing Libraries and Tools
Master document processing for LLMs with this comprehensive guide covering open-source libraries, premium APIs, and cloud services. Compare PyMuPDF, Unstructured.io, Docling, and LlamaParse for your RAG systems.
AI Engineering