What are custom hooks?
In React, custom hooks let you extract and reuse stateful logic across multiple components. They are JavaScript functions that use built-in hooks like useState
, useEffect
, or useRef
, and follow the naming convention useSomething
.
Custom hooks don’t add new functionality to React, but they help you organize code more cleanly and reduce duplication.
Why use custom hooks?
Benefit | Explanation |
Reusability | Avoid repeating logic across components |
Clean components | Move logic out of the component body |
Testability | Logic in hooks can be unit tested independently |
Separation of concerns | Keeps UI and logic separate |
Basic structure of a custom hook
import { useState, useEffect } from 'react';
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return width;
}
Usage in a component:
function MyComponent() {
const width = useWindowWidth();
return <p>Window width: {width}px</p>;
}
Guidelines for writing custom hooks
- Prefix with
use
to follow React’s rules of hooks - Use other hooks inside (e.g.,
useState
,useEffect
) - Keep them pure and focused on a single task
- Return only what is needed (state, handlers, values)
More useful examples
1. Uselocalstorage
function useLocalStorage(key, initialValue) {
const [value, setValue] = useState(() => {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue];
}
2. Usefetch
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(setData)
.finally(() => setLoading(false));
}, [url]);
return { data, loading };
}
When should you create a custom hook?
Create one when:
- Multiple components share the same logic (e.g., form handling, API calls)
- Logic inside a component gets too large
- You want to abstract side effects (e.g., subscriptions, listeners)
- You want better test coverage for business logic
Best practices
- Follow React's Rules of Hooks
- Don’t use hooks conditionally inside your custom hook
- Keep return values intuitive and well-documented
- Combine hooks when necessary (e.g.,
useState
+useEffect
) - Test hooks using tools like React Testing Library and
@testing-library/react-hooks
Conclusion
Custom hooks are a powerful way to write cleaner, more modular React code. By abstracting logic into reusable functions, you can improve your app’s maintainability and reduce complexity in your components. Start simple, and extract logic as your components grow!