🧭 Introduction
One of the biggest advantages of React Hooks is the ability to create custom hooks.
But here’s the reality:
❌ Most developers create custom hooks too early
❌ Many custom hooks are just copied useEffect blocks
❌ Poorly designed hooks become harder to maintain than components
A good custom hook is not about writing less code —
it’s about writing reusable, readable, and predictable logic.
In this lesson, you’ll learn how senior developers design custom hooks, not just how to write them.
🎯 What You’ll Learn in This Lesson
By the end of this lesson, you will understand:
- What a custom hook really is
- When you should create a custom hook
- Rules and conventions for custom hooks
- Characteristics of a good custom hook
- Common mistakes and anti-patterns
🧠 What Is a Custom Hook? (Correct Definition)
A custom hook is:
A JavaScript function that uses one or more React hooks
and encapsulates reusable, non-UI logic.
Key points:
- Starts with
use - Can use other hooks
- Does not return JSX
- Focuses on logic, not UI
✅ Basic Custom Hook Example
function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);
const increment = () => setCount(c => c + 1);
const decrement = () => setCount(c => c - 1);
return { count, increment, decrement };
}
Usage:
const { count, increment, decrement } = useCounter();
❓ When Should You Create a Custom Hook?
Create a custom hook when:
✅ Logic is reused in multiple components
✅ Component code becomes hard to read
✅ Same useEffect logic appears repeatedly
✅ State + side effects belong together
❌ Do NOT create a custom hook just to “look advanced”.
🧠 Mental Model (Very Important)
Components = UI
Hooks = Logic
If your hook starts returning JSX —
you are breaking the mental model.
🧩 Rules of Custom Hooks
Custom hooks follow all Rules of Hooks:
1️⃣ Must start with use
2️⃣ Must be called at the top level
3️⃣ Must not be called conditionally
4️⃣ Can call other hooks
React relies on these rules to track hook state.
🔑 Characteristics of a Good Custom Hook
✅ 1. Single Responsibility
A hook should do one thing well.
❌ Bad:
useFormAndApiAndValidation()
✅ Good:
useForm()
useFetch()
useValidation()
✅ 2. Reusable Without Modification
A good hook:
- Works in multiple components
- Is not tightly coupled to UI
❌ Avoid hardcoded UI logic.
✅ 3. Clean, Predictable API
The hook’s return value should be easy to understand.
const { data, loading, error } = useFetch(url);
Clear. Predictable. Professional.
✅ 4. Hides Internal Complexity
Consumers should not know:
- How many effects are used
- How state is managed
They only care about results.
🔍 Example — Bad vs Good Custom Hook
❌ Bad Custom Hook
function useData() {
const [data, setData] = useState([]);
useEffect(() => {
fetch("/api").then(res => res.json()).then(setData);
}, []);
return data;
}
Problems:
- No loading state
- No error handling
- Hardcoded URL
✅ Good Custom Hook
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
fetch(url)
.then(res => res.json())
.then(setData)
.catch(setError)
.finally(() => setLoading(false));
}, [url]);
return { data, loading, error };
}
Reusable. Predictable. Clean.
🚨 Common Custom Hook Mistakes
❌ Mistake 1: Returning JSX
Hooks should not render UI.
❌ Mistake 2: Too Many Responsibilities
Large hooks become unmaintainable.
❌ Mistake 3: Hiding Too Much Magic
Over-abstracting makes debugging harder.
❌ Mistake 4: Breaking Hook Rules
Calling hooks conditionally inside custom hooks is still illegal.
🧠 Custom Hooks vs Components
| Aspect | Component | Custom Hook |
|---|---|---|
| Purpose | UI | Logic |
| Returns | JSX | Values / functions |
| Reusability | Limited | High |
| Side effects | Yes | Yes |
🔍 Real-World Custom Hooks Examples
Professional projects use hooks like:
useAuthuseFetchuseDebounceuseLocalStorageuseMediaQuery
These hooks:
- Encapsulate logic
- Keep components clean
- Improve testability
🎯 Best Practices (Senior-Level)
✅ Write hooks only when logic repeats
✅ Keep APIs simple and expressive
✅ Avoid premature abstraction
✅ Prefer readability over cleverness
✅ Document hook behavior clearly
❓ FAQs — Custom Hooks
🔹 Can a custom hook use another custom hook?
Yes — that’s a common and powerful pattern.
🔹 Can hooks manage global state?
Yes, when combined with Context or external stores.
🔹 Should every component have its own hook?
No. Only when logic is reusable.
🔹 Are custom hooks hard to test?
No — they are often easier to test than components.
🧠 Quick Recap
✔ Custom hooks encapsulate logic
✔ They do not render UI
✔ Good hooks are reusable and predictable
✔ Avoid over-engineering
✔ Hooks improve code quality when used correctly
🎉 Conclusion
A good custom hook is invisible —
you don’t notice it, you just enjoy clean components.
Once you master custom hooks:
- Your components become smaller
- Your logic becomes reusable
- Your codebase scales gracefully
This lesson sets the foundation for real-world hook design ⚛️🧠
👉 Next Lesson
Lesson 10 — Utility Custom Hooks (useToggle, useDebounce)