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., useCounterreturning 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 : useAuthto manage user login/logout state.
- 
Theme Management : useThemefor switching between light and dark modes.
- 
Form Handling : useFormfor input validation and state management.
- 
Debouncing : useDebounceto handle delayed API calls (e.g., search queries).
- 
Animations : useAnimationto 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 useEffector 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)