DEV Community

Harshit Singh
Harshit Singh

Posted on

6

Custom Hooks in React: A Guide to Creation and Usage

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?

  1. Reusability : Avoid duplicating logic across multiple components.
  2. Separation of Concerns : Keep your component code focused on rendering, moving business logic into a custom hook.
  3. Improved Readability : Makes components easier to understand by offloading complex operations.
  4. 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.

  1. Import Necessary Built-in Hooks :
import { useState, useEffect } from 'react';

Enter fullscreen mode Exit fullscreen mode
  1. 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;
}

Enter fullscreen mode Exit fullscreen mode
  1. 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;

Enter fullscreen mode Exit fullscreen mode

Key Guidelines for Custom Hooks

  1. Naming : Always start the function name with use. This convention ensures React recognizes it as a hook and validates its usage.
  2. Hook Rules : Custom hooks must follow the Rules of Hooks , i.e., they:
  3. Can only be called at the top level of a function.
  4. Can only be used within React functional components or other custom hooks.
  5. Return What You Need : Custom hooks can return:
  6. A value (e.g., a state variable).
  7. An object (e.g., multiple states and functions).
  8. 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;

Enter fullscreen mode Exit fullscreen mode

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>
  );
}

Enter fullscreen mode Exit fullscreen mode

Real-World Applications of Custom Hooks

  1. Authentication : useAuth to manage user login/logout state.
  2. Theme Management : useTheme for switching between light and dark modes.
  3. Form Handling : useForm for input validation and state management.
  4. Debouncing : useDebounce to handle delayed API calls (e.g., search queries).
  5. 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.

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)