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.
Top comments (0)