Custom Hooks in React: A Guide to Creation and Usage
Harshit Singh
Posted on November 21, 2024
React’s built-in hooks are powerful, but sometimes we encounter scenarios that require shared logic across multiple components. That’s where custom hooks come in! They allow us to abstract reusable logic into a function that utilizes React hooks. Here’s everything you need to know about creating and using custom hooks.
What Are Custom Hooks?
Custom hooks are JavaScript functions that:
- Start with the prefix
use
(e.g.,useMyCustomLogic
). - Encapsulate and reuse logic that involves one or more built-in React hooks.
They make your code cleaner, more modular, and easier to maintain.
Why Create Custom Hooks?
- Reusability : Avoid duplicating logic across multiple components.
- Separation of Concerns : Keep your component code focused on rendering, moving business logic into a custom hook.
- Improved Readability : Makes components easier to understand by offloading complex operations.
- Testability : Hooks are easier to test than testing the logic embedded within components.
How to Create a Custom Hook Step-by-Step Example: useWindowSize
**
Let's create a hook that tracks the window's width and height.
- Import Necessary Built-in Hooks :
import { useState, useEffect } from 'react';
- Define the Custom Hook :
function useWindowSize() {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
useEffect(() => {
// Handler to update window size
const handleResize = () => {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
};
// Attach the event listener
window.addEventListener('resize', handleResize);
// Cleanup listener on unmount
return () => window.removeEventListener('resize', handleResize);
}, []); // Empty dependency array ensures this runs once on mount
return windowSize;
}
- Use Your Hook in a Component :
function App() {
const { width, height } = useWindowSize();
return (
<div>
<h1>Window Size</h1>
<p>Width: {width}px</p>
<p>Height: {height}px</p>
</div>
);
}
export default App;
Key Guidelines for Custom Hooks
-
Naming : Always start the function name with
use
. This convention ensures React recognizes it as a hook and validates its usage. - Hook Rules : Custom hooks must follow the Rules of Hooks , i.e., they:
- Can only be called at the top level of a function.
- Can only be used within React functional components or other custom hooks.
- Return What You Need : Custom hooks can return:
- A value (e.g., a state variable).
- An object (e.g., multiple states and functions).
- A function (e.g.,
useCounter
returning increment and decrement functions).
Advanced Example: useFetch
**
Here’s a more dynamic custom hook to handle API requests.
import { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(url);
if (!response.ok) throw new Error('Network response was not ok');
const json = await response.json();
setData(json);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
fetchData();
}, [url]); // Runs whenever the URL changes
return { data, loading, error };
}
export default useFetch;
Usage:
function UserList() {
const { data, loading, error } = useFetch('<https://jsonplaceholder.typicode.com/users>');
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error}</p>;
return (
<ul>
{data.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
Real-World Applications of Custom Hooks
-
Authentication :
useAuth
to manage user login/logout state. -
Theme Management :
useTheme
for switching between light and dark modes. -
Form Handling :
useForm
for input validation and state management. -
Debouncing :
useDebounce
to handle delayed API calls (e.g., search queries). -
Animations :
useAnimation
to abstract animation logic.
Testing Custom Hooks Custom hooks can be tested using libraries like React Testing Library or Jest . A typical test might involve:
- Mocking
useEffect
or external dependencies. - Testing the output based on different inputs.
Custom hooks enable cleaner, reusable, and scalable codebases . They embody the true power of React, making your application logic modular and easier to maintain.
Posted on November 21, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.