DEV Community

Cover image for Top 10 Most Useful Custom Hooks in React
Sariah for SkillReactor

Posted on • Originally published at skillreactor.io

Top 10 Most Useful Custom Hooks in React

React's custom hooks have transformed how developers construct reusable logic and distribute functionality across components. These hooks encapsulate prevalent patterns and behaviors, simplifying the creation of cleaner, more maintainable code. In this article, we will explore the ten most beneficial custom hooks in React, complemented by code examples illustrating their practical utility.

1. UseLocalStorage:

Managing data in local storage is a common task in web development. The useLocalStorage hook simplifies this process by providing a convenient way to read from and write to local storage.

import { useState } from 'react';

function useLocalStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.error(error);
      return initialValue;
    }
  });

  const setValue = value => {
    try {
      setStoredValue(value);
      window.localStorage.setItem(key, JSON.stringify(value));
    } catch (error) {
      console.error(error);
    }
  };

  return [storedValue, setValue];
}

// Usage
const [name, setName] = useLocalStorage('name', 'John');
Enter fullscreen mode Exit fullscreen mode

2. UseForm:

Handling form state and validation can be repetitive. The useForm hook simplifies this process by managing form state, validation, and submission logic in a reusable manner.

import { useState } from 'react';

function useForm(initialValues, validate) {
  const [values, setValues] = useState(initialValues);
  const [errors, setErrors] = useState({});

  const handleChange = event => {
    const { name, value } = event.target;
    setValues({ ...values, [name]: value });
  };

  const handleSubmit = event => {
    event.preventDefault();
    const validationErrors = validate(values);
    setErrors(validationErrors);
    if (Object.keys(validationErrors).length === 0) {
      // Handle form submission
    }
  };

  return { values, errors, handleChange, handleSubmit };
}

// Usage
const { values, errors, handleChange, handleSubmit } = useForm(
  { email: '', password: '' },
  values => {
    let errors = {};
    if (!values.email) {
      errors.email = 'Email is required';
    }
    if (!values.password) {
      errors.password = 'Password is required';
    }
    return errors;
  }
);
Enter fullscreen mode Exit fullscreen mode

3. UseFetch:

Fetching data from APIs is a common task in web applications. The useFetch hook simplifies data fetching by providing a simple interface for making HTTP requests and handling loading, error, and data states.

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);
        const jsonData = await response.json();
        setData(jsonData);
      } catch (error) {
        setError(error);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading, error };
}

// Usage
const { data, loading, error } = useFetch('https://api.example.com/data');
Enter fullscreen mode Exit fullscreen mode

4. UseMediaQuery:

Creating responsive layouts is crucial for modern web development. The useMediaQuery hook enables developers to conditionally render components based on the user's device or screen size.

import { useState, useEffect } from 'react';

function useMediaQuery(query) {
  const [matches, setMatches] = useState(false);

  useEffect(() => {
    const mediaQuery = window.matchMedia(query);
    const handleChange = () => setMatches(mediaQuery.matches);

    setMatches(mediaQuery.matches);
    mediaQuery.addListener(handleChange);

    return () => {
      mediaQuery.removeListener(handleChange);
    };
  }, [query]);

  return matches;
}

// Usage
const isMobile = useMediaQuery('(max-width: 768px)');
Enter fullscreen mode Exit fullscreen mode

5. UseScroll:

Tracking scroll position and implementing scroll-based effects are common requirements in web development. The useScroll hook provides access to the scroll position and handles scroll event listeners.

import { useState, useEffect } from 'react';

function useScroll() {
  const [scrollPosition, setScrollPosition] = useState(0);

  useEffect(() => {
    const handleScroll = () => {
      setScrollPosition(window.scrollY);
    };

    window.addEventListener('scroll', handleScroll);

    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, []);

  return scrollPosition;
}

// Usage
const scrollPosition = useScroll();
Enter fullscreen mode Exit fullscreen mode

6. UseIntersectionObserver:

The Intersection Observer API is useful for detecting when an element enters or exits the viewport. The useIntersectionObserver hook encapsulates this functionality, enabling lazy-loaded images, infinite scroll, and other dynamic behaviors.

import { useState, useEffect } from 'react';

function useIntersectionObserver(ref, options) {
  const [intersecting, setIntersecting] = useState(false);

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        setIntersecting(entry.isIntersecting);
      },
      options
    );

    if (ref.current) {
      observer.observe(ref.current);
    }

    return () => {
      observer.disconnect();
    };
  }, [ref, options]);

  return intersecting;
}

// Usage
const ref = useRef(null);
const intersecting = useIntersectionObserver(ref, { threshold: 0.5 });
Enter fullscreen mode Exit fullscreen mode

7. UseAnimation:

Animating elements in React can be challenging. The useAnimation hook simplifies this task by abstracting away the complexities of animation libraries like GSAP or Framer Motion.

import { useRef, useEffect } from 'react';
import { gsap } from 'gsap';

function useAnimation(options) {
  const elementRef = useRef(null);

  useEffect(() => {
    const element = elementRef.current;
    if (element) {
      gsap.to(element, options);
    }
  }, [options]);

  return elementRef;
}

// Usage
const animationRef = useAnimation({ opacity: 0, duration: 1 });
Enter fullscreen mode Exit fullscreen mode

8. UseDebounce:

Debouncing is useful for delaying the execution of a function until after a specified period of inactivity. The useDebounce hook helps mitigate performance issues by debouncing expensive operations such as API requests or search input handling.

import { useState, useEffect } from 'react';

function useDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);

  return debouncedValue;
}

// Usage
const debouncedValue = useDebounce(inputValue, 300);
Enter fullscreen mode Exit fullscreen mode

9. UseThrottle:

Similar to debouncing, throttling limits the rate at which a function is executed. The useThrottle hook is useful for scenarios where you want to limit the frequency of event handlers, such as scroll or resize events.

import { useState, useEffect } from 'react';

function useThrottle(value, delay) {
  const [throttledValue, setThrottledValue] = useState(value);
  const [lastExecuted, setLastExecuted] = useState(Date.now());

  useEffect(() => {
    const handler = setTimeout(() => {
      setThrottledValue(value);
      setLastExecuted(Date.now());
    }, delay);

    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);

  return throttledValue;
}

// Usage
const throttledValue = useThrottle(inputValue, 300);
Enter fullscreen mode Exit fullscreen mode

10. UseAuthentication:

Managing user authentication state is a common requirement in web applications. The useAuthentication hook abstracts away the complexities of authentication logic, handling login/logout actions, and persisting authentication tokens securely.

import { useState } from 'react';

function useAuthentication() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  const login = () => {
    // Perform login logic
    setIsLoggedIn(true);
  };

  const logout = () => {
    // Perform logout logic
    setIsLoggedIn(false);
  };

  return { isLoggedIn, login, logout };
}

// Usage
const { isLoggedIn, login, logout } = useAuthentication();
Enter fullscreen mode Exit fullscreen mode

Conclusion:
Custom hooks are powerful tools that enable developers to encapsulate and reuse logic across React components. By leveraging the top 10 most useful custom hooks outlined in this article, developers can streamline common tasks, enhance application functionality, and build better user experiences in their React applications.

If you are a React developer looking to level up, SkillReactor is an online platform with real-world for React developers to enhance their skills. It provides feedback from code reviews and enables developers to build a portfolio of React projects to showcase their expertise.

Top comments (0)