DEV Community

Cover image for Top 30 React hooks every developer must know
Kumar Kalyan
Kumar Kalyan

Posted on

Top 30 React hooks every developer must know

Save the article

React is an open source JavaScript library for building awesome and complex user interfaces and is one of the most popular in the JavaScript ecosystem.

TLDR 📜

React hooks are functions that allow you to use React state and other features within functional components, enabling tasks like handling side effects and accessing context without writing complex React classes. Using React hooks also enhances code readability and maintainability for developers.

In this article, I will share a list of the 38 React.js hooks and their use cases, which can be considered one of the best resources for React and JavaScript developers.

Jeremy Says

1. useState

Manages local component state.

import { useState } from 'react';
function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <p>Count: {count}</p>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

2. useEffect

Performs side effects in function components.

import { useEffect, useState } from 'react';

function DataFetcher() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => setData(data));
  }, []);

  return <div>Data: {data ? JSON.stringify(data) : 'Loading...'}</div>;
}

Enter fullscreen mode Exit fullscreen mode

3. useContext

Consumes context in a component.

import { useContext } from 'react';
import { ThemeContext } from './ThemeContext';

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button style={{ background: theme.background }}>Click me</button>;
}

Enter fullscreen mode Exit fullscreen mode

4.useReducer

Manages complex state logic

import { useReducer } from 'react';

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <div>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
      <span>{state.count}</span>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

5. useCallback

Returns a memoized callback function.

import { useCallback, useState } from 'react';

function CallbackComponent() {
  const [count, setCount] = useState(0);

  const increment = useCallback(() => {
    setCount(count + 1);
  }, [count]);

  return <button onClick={increment}>Count: {count}</button>;
}

Enter fullscreen mode Exit fullscreen mode

6. useMemo

Memoizes expensive calculations i.e stores results of resource-intensive calculations for future use.

import { useMemo, useState } from 'react';

function Fibonacci() {
  const [num, setNum] = useState(1);

  const fib = useMemo(() => {
    const computeFib = (n) => (n <= 1 ? n : computeFib(n - 1) + computeFib(n - 2));
    return computeFib(num);
  }, [num]);

  return (
    <div>
      <button onClick={() => setNum(num + 1)}>Next Fibonacci</button>
      <p>Fibonacci of {num} is {fib}</p>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

7.useRef

Accesses DOM elements or stores mutable values.

import { useRef } from 'react';

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    inputEl.current.focus();
  };

  return (
    <div>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

8.useImperativeHandle

Customizes the instance value exposed by a ref.

import { forwardRef, useImperativeHandle, useRef } from 'react';

const FancyInput = forwardRef((props, ref) => {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    },
  }));
  return <input ref={inputRef} />;
});

function App() {
  const fancyInputRef = useRef();
  return (
    <div>
      <FancyInput ref={fancyInputRef} />
      <button onClick={() => fancyInputRef.current.focus()}>Focus input</button>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

9. useLayoutEffect

Synchronizes with the DOM layout.

import { useEffect, useLayoutEffect, useRef, useState } from 'react';

function MeasureWidth() {
  const ref = useRef();
  const [width, setWidth] = useState(0);

  useLayoutEffect(() => {
    setWidth(ref.current.offsetWidth);
  }, []);

  return (
    <div>
      <div ref={ref} style={{ width: '50%' }}>
        Resize the window to see the effect.
      </div>
      <p>Width: {width}px</p>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

10.useDebugValue

Displays custom label in React DevTools.

import { useDebugValue, useState } from 'react';

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  useDebugValue(isOnline ? 'Online' : 'Offline');

  // Simulate an asynchronous operation
  setTimeout(() => setIsOnline(Math.random() > 0.5), 1000);

  return isOnline;
}

function FriendStatus({ friendID }) {
  const isOnline = useFriendStatus(friendID);

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}

Enter fullscreen mode Exit fullscreen mode

11.useFetch

Fetches data from an API.

import { useEffect, useState } from 'react';

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch(url)
      .then(response => response.json())
      .then(data => {
        setData(data);
        setLoading(false);
      });
  }, [url]);

  return { data, loading };
}

function App() {
  const { data, loading } = useFetch('https://jsonplaceholder.typicode.com/posts');

  if (loading) {
    return <p>Loading...</p>;
  }

  return (
    <ul>
      {data.map(post => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

Enter fullscreen mode Exit fullscreen mode

12.useLocalStorage

Manages state with 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 {
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      window.localStorage.setItem(key, JSON.stringify(valueToStore));
    } catch (error) {
      console.error(error);
    }
  };

  return [storedValue, setValue];
}

function App() {
  const [name, setName] = useLocalStorage('name', 'Bob');

  return (
    <div>
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <p>Hello, {name}!</p>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

13. useDebounce

Debounces a value over time.

import { useEffect, useState } 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;
}

function App() {
  const [text, setText] = useState('');
  const debouncedText = useDebounce(text, 500);

  return (
    <div>
      <input value={text} onChange={(e) => setText(e.target.value)} />
      <p>Debounced Value: {debouncedText}</p>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

14.usePrevious

Stores the previous value of a variable.

import { useEffect, useRef } from 'react';

function usePrevious(value) {
  const ref = useRef();

  useEffect(() => {
    ref.current = value;
  }, [value]);

  return ref.current;
}

function App() {
  const [count, setCount] = useState(0);
  const previousCount = usePrevious(count);

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Count: {count}</button>
      <p>Previous Count: {previousCount}</p>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

15. useWindowSize

Tracks window size.

import { useEffect, useState } from 'react';

function useWindowSize() {
  const [size, setSize] = useState({ width: window.innerWidth, height: window.innerHeight });

  useEffect(() => {
    const handleResize = () => {
      setSize({ width: window.innerWidth, height: window.innerHeight });
    };

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return size;
}

function App() {
  const { width, height } = useWindowSize();

  return (
    <div>
      <p>Width: {width}px</p>
      <p>Height: {height}px</p>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

16.useHover

Detects if an element is hovered.

import { useCallback, useState } from 'react';

function useHover() {
  const [hovered, setHovered] = useState(false);

  const onMouseOver = useCallback(() => setHovered(true), []);
  const onMouseOut = useCallback(() => setHovered(false), []);

  return { hovered, onMouseOver, onMouseOut };
}

function HoverComponent() {
  const { hovered, onMouseOver, onMouseOut } = useHover();

  return (
    <div onMouseOver={onMouseOver} onMouseOut={onMouseOut}>
      {hovered ? 'Hovering' : 'Not Hovering'}
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

17. useOnlineStatus

Tracks online status.

import { useEffect, useState } from 'react';

function useOnlineStatus() {
  const [isOnline, setIsOnline] = useState(navigator.onLine);

  useEffect(() => {
    const handleOnline = () => setIsOnline(true);
    const handleOffline = () => setIsOnline(false);

    window.addEventListener('online', handleOnline);
    window.addEventListener('offline', handleOffline);

    return () => {
      window.removeEventListener('online', handleOnline);
      window.removeEventListener('offline', handleOffline);
    };
  }, []);

  return isOnline;
}

function App() {
  const isOnline = useOnlineStatus();

  return <div>{isOnline ? 'Online' : 'Offline'}</div>;
}

Enter fullscreen mode Exit fullscreen mode

18. useEventListener

Attaches an event listener.

import { useEffect, useRef } from 'react';

function useEventListener(eventName, handler, element = window) {
  const savedHandler = useRef();

  useEffect(() => {
    savedHandler.current = handler;
  }, [handler]);

  useEffect(() => {
    const eventListener = (event) => savedHandler.current(event);
    element.addEventListener(eventName, eventListener);

    return () => {
      element.removeEventListener(eventName, eventListener);
    };
  }, [eventName, element]);
}

function App() {
  useEventListener('click', () => alert('Window clicked!'));

  return <div>Click anywhere!</div>;
}

Enter fullscreen mode Exit fullscreen mode

19.useInterval

Sets up an interval with a dynamic delay.

import { useEffect, useRef } from 'react';

function useInterval(callback, delay) {
  const savedCallback = useRef();

  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    if (delay !== null) {
      const id = setInterval(tick, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}

function Timer() {
  const [count, setCount] = useState(0);

  useInterval(() => setCount(count + 1), 1000);

  return <div>Count: {count}</div>;
}

Enter fullscreen mode Exit fullscreen mode

20. useTimeout

Sets up a timeout.

import { useEffect, useRef } from 'react';

function useTimeout(callback, delay) {
  const savedCallback = useRef();

  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    if (delay !== null) {
      const id = setTimeout(tick, delay);
      return () => clearTimeout(id);
    }
  }, [delay]);
}

function App() {
  const [visible, setVisible] = useState(true);

  useTimeout(() => setVisible(false), 5000);

  return <div>{visible ? 'Visible for 5 seconds' : 'Hidden'}</div>;
}

Enter fullscreen mode Exit fullscreen mode

21. useOnClickOutside

Detects clicks outside a component.

import { useEffect, useRef } from 'react';

function useOnClickOutside(ref, handler) {
  useEffect(() => {
    const listener = (event) => {
      if (!ref.current || ref.current.contains(event.target)) {
        return;
      }
      handler(event);
    };

    document.addEventListener('mousedown', listener);
    document.addEventListener('touchstart', listener);

    return () => {
      document.removeEventListener('mousedown', listener);
      document.removeEventListener('touchstart', listener);
    };
  }, [ref, handler]);
}

function App() {
  const ref = useRef();
  const [isVisible, setIsVisible] = useState(true);

  useOnClickOutside(ref, () => setIsVisible(false));

  return (
    <div>
      <div ref={ref} style={{ display: isVisible ? 'block' : 'none' }}>
        Click outside this box to hide it.
      </div>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

22. useClipboard

Handles clipboard operations.

import { useState } from 'react';

function useClipboard() {
  const [copied, setCopied] = useState(false);

  const copy = (text) => {
    navigator.clipboard.writeText(text).then(() => setCopied(true));
  };

  return { copied, copy };
}

function App() {
  const { copied, copy } = useClipboard();

  return (
    <div>
      <button onClick={() => copy('Hello, world!')}>
        {copied ? 'Copied!' : 'Copy'}
      </button>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

23. useDarkMode

Manages dark mode preference.

import { useEffect, useState } from 'react';

function useDarkMode() {
  const [isDarkMode, setIsDarkMode] = useState(false);

  useEffect(() => {
    const darkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
    setIsDarkMode(darkMode);
  }, []);

  return isDarkMode;
}

function App() {
  const isDarkMode = useDarkMode();

  return <div>{isDarkMode ? 'Dark Mode' : 'Light Mode'}</div>;
}

Enter fullscreen mode Exit fullscreen mode

24.useToggle

Toggles between boolean values.

import { useState } from 'react';

function useToggle(initialValue = false) {
  const [value, setValue] = useState(initialValue);
  const toggle = () => setValue(!value);
  return [value, toggle];
}

function App() {
  const [isToggled, toggle] = useToggle();

  return (
    <div>
      <button onClick={toggle}>{isToggled ? 'On' : 'Off'}</button>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

25. useTheme

Toggles between light and dark themes.

import { useEffect, useState } from 'react';

function useTheme() {
  const [theme, setTheme] = useState('light');

  useEffect(() => {
    document.body.className = theme;
  }, [theme]);

  const toggleTheme = () => {
    setTheme((prevTheme) => (prevTheme === 'light' ? 'dark' : 'light'));
  };

  return { theme, toggleTheme };
}

function App() {
  const { theme, toggleTheme } = useTheme();

  return (
    <div>
      <p>Current Theme: {theme}</p>
      <button onClick={toggleTheme}>Toggle Theme</button>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

26. useMedia

Queries media properties.

import { useEffect, useState } from 'react';

function useMedia(query) {
  const [matches, setMatches] = useState(window.matchMedia(query).matches);

  useEffect(() => {
    const mediaQueryList = window.matchMedia(query);
    const listener = (event) => setMatches(event.matches);

    mediaQueryList.addListener(listener);
    return () => mediaQueryList.removeListener(listener);
  }, [query]);

  return matches;
}

function App() {
  const isLargeScreen = useMedia('(min-width: 800px)');

  return <div>{isLargeScreen ? 'Large Screen' : 'Small Screen'}</div>;
}

Enter fullscreen mode Exit fullscreen mode

27. useLockBodyScroll

Locks the body scroll.

import { useEffect } from 'react';

function useLockBodyScroll() {
  useEffect(() => {
    const originalOverflow = window.getComputedStyle(document.body).overflow;
    document.body.style.overflow = 'hidden';
    return () => (document.body.style.overflow = originalOverflow);
  }, []);
}

function App() {
  useLockBodyScroll();

  return <div>Body scroll is locked</div>;
}

Enter fullscreen mode Exit fullscreen mode

28.useKeyPress

Detects key press.

import { useEffect, useState } from 'react';

function useKeyPress(targetKey) {
  const [keyPressed, setKeyPressed] = useState(false);

  useEffect(() => {
    const downHandler = ({ key }) => {
      if (key === targetKey) setKeyPressed(true);
    };

    const upHandler = ({ key }) => {
      if (key === targetKey) setKeyPressed(false);
    };

    window.addEventListener('keydown', downHandler);
    window.addEventListener('keyup', upHandler);

    return () => {
      window.removeEventListener('keydown', downHandler);
      window.removeEventListener('keyup', upHandler);
    };
  }, [targetKey]);

  return keyPressed;
}

function App() {
  const aPressed = useKeyPress('a');

  return <div>{aPressed ? 'A is pressed' : 'Press A'}</div>;
}

Enter fullscreen mode Exit fullscreen mode

29. useDocumentTitle

Updates document title.

import { useEffect } from 'react';

function useDocumentTitle(title) {
  useEffect(() => {
    document.title = title;
  }, [title]);
}

function App() {
  useDocumentTitle('Custom Title');

  return <div>Check the document title</div>;
}

Enter fullscreen mode Exit fullscreen mode

30. useHover

Handles hover state.

import { useCallback, useState } from 'react';

function useHover() {
  const [hovered, setHovered] = useState(false);

  const onMouseOver = useCallback(() => setHovered(true), []);
  const onMouseOut = useCallback(() => setHovered(false), []);

  return { hovered, onMouseOver, onMouseOut };
}

function HoverComponent() {
  const { hovered, onMouseOver, onMouseOut } = useHover();

  return (
    <div onMouseOver={onMouseOver} onMouseOut={onMouseOut}>
      {hovered ? 'Hovering' : 'Not Hovering'}
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

31.useGeolocation

Retrieves geolocation.

import { useEffect, useState } from 'react';

function useGeolocation() {
  const [location, setLocation] = useState({});

  useEffect(() => {
    navigator.geolocation.getCurrentPosition(
      (position) => setLocation(position.coords),
      (error) => console.error(error)
    );
  }, []);

  return location;
}

function App() {
  const { latitude, longitude } = useGeolocation();

  return (
    <div>
      <p>Latitude: {latitude}</p>
      <p>Longitude: {longitude}</p>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

32. useScrollPosition

Tracks scroll position.

import { useEffect, useState } from 'react';

function useScrollPosition() {
  const [position, setPosition] = useState({ x: 0, y: 0 });

  useEffect(() => {
    const handleScroll = () => {
      setPosition({ x: window.scrollX, y: window.scrollY });
    };

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

  return position;
}

function App() {
  const { x, y } = useScrollPosition();

  return (
    <div>
      <p>Scroll Position: {`x: ${x}, y: ${y}`}</p>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

33. useUnmount

Runs a function when a component unmounts.

import { useEffect } from 'react';

function useUnmount(callback) {
  useEffect(() => {
    return () => callback();
  }, [callback]);
}

function App() {
  useUnmount(() => {
    console.log('Component will unmount');
  });

  return <div>Unmount me to see the console message.</div>;
}

Enter fullscreen mode Exit fullscreen mode

34. useClickOutside

Detects clicks outside an element.

import { useEffect, useRef } from 'react';

function useClickOutside(handler) {
  const ref = useRef();

  useEffect(() => {
    const listener = (event) => {
      if (!ref.current || ref.current.contains(event.target)) {
        return;
      }
      handler(event);
    };

    document.addEventListener('mousedown', listener);
    document.addEventListener('touchstart', listener);

    return () => {
      document.removeEventListener('mousedown', listener);
      document.removeEventListener('touchstart', listener);
    };
  }, [handler]);

  return ref;
}

function App() {
  const handleClickOutside = () => {
    console.log('Clicked outside!');
  };

  const ref = useClickOutside(handleClickOutside);

  return (
    <div ref={ref} style={{ padding: '50px', border: '1px solid black' }}>
      Click outside me!
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

35. useDebouncedCallback

Debounces a callback function.

import { useCallback, useState } from 'react';

function useDebouncedCallback(callback, delay) {
  const [timeoutId, setTimeoutId] = useState(null);

  const debouncedCallback = useCallback((...args) => {
    if (timeoutId) {
      clearTimeout(timeoutId);
    }
    const id = setTimeout(() => {
      callback(...args);
    }, delay);
    setTimeoutId(id);
  }, [callback, delay]);

  return debouncedCallback;
}

function App() {
  const [value, setValue] = useState('');
  const handleChange = useDebouncedCallback((e) => {
    setValue(e.target.value);
  }, 500);

  return (
    <input type="text" onChange={handleChange} />
  );
}

Enter fullscreen mode Exit fullscreen mode

36. useThrottle

Throttles a value over time.

import { useEffect, useState } from 'react';

function useThrottle(value, limit) {
  const [throttledValue, setThrottledValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setThrottledValue(value);
    }, limit);

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

  return throttledValue;
}

function App() {
  const [text, setText] = useState('');
  const throttledText = useThrottle(text, 1000);

  return (
    <div>
      <input value={text} onChange={(e) => setText(e.target.value)} />
      <p>Throttled Value: {throttledText}</p>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

37. useUpdateEffect

Runs an effect only on updates, not on mount.

import { useEffect, useRef } from 'react';

function useUpdateEffect(effect, dependencies) {
  const isInitialMount = useRef(true);

  useEffect(() => {
    if (isInitialMount.current) {
      isInitialMount.current = false;
    } else {
      effect();
    }
  }, dependencies);
}

function App() {
  const [count, setCount] = useState(0);

  useUpdateEffect(() => {
    console.log('Component updated');
  }, [count]);

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <p>Count: {count}</p>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

38.useLocalStorage

Manages state in local storage

import { useEffect, 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];
}

function App() {
  const [name, setName] = useLocalStorage('name', 'Guest');

  return (
    <div>
      <input value={name} onChange={(e) => setName(e.target.value)} />
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

React.js is easy to learn and master, with numerous free courses and resources, plus a massive and active developer community
Make sure to use these React hooks in your next project and follow me for more content like this

GIF CREDIT

If you like the gif make sure to follow Jeremy the manager on instagram

Top comments (0)