DEV Community

Cover image for React hooks nobody told you before
Kumar Kalyan
Kumar Kalyan

Posted on

React hooks nobody told you before

TLDR 🔥

React.js is one of the most popular JavaScript libraries for building beautiful user interfaces and single-page applications. And the average salary of a react developer goes up to 100K usd a year . React is used by some of the most popular tech companies around the world. The React ecosystem is vast and has a huge number of supporting libraries and frameworks, which give React additional powers to build full-stack, production-grade applications. The key features of React include component-driven architecture, the use of a virtual DOM, one-way data binding, and many more. However, in this particular article, I will focus on one of the most important features of React: hooks. I will explain the concept of hooks in detail.

  • What are react hooks and their importance
  • 38 react hooks you must know as a react developer along with code

learn react js make 100k usd a year

What are hooks in react and their importance?

Hooks in React allow developers to use the state of a React application without using classes. This helps React developers write clean and reusable components with fewer lines of code. Knowledge of React hooks will help you excel in React interviews, as it is one of the most important topics asked by interviewers in every React interview.

The top 38 react hooks

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
  1. useMemo Memoizes expensive calculations.
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

learn react js make 100k usd a year

conclusion

In this article you learned about the top 38 react hooks and their use cases. Make sure to use these hooks in you code and stay tuned for the next article.

Top comments (0)