DEV Community

Cover image for 🪝 The Ultimate React Hooks Cheat Sheet (2025 Edition)
D3Y4N
D3Y4N

Posted on

🪝 The Ultimate React Hooks Cheat Sheet (2025 Edition)

React keeps adding crazy powerful hooks… and remembering them all feels like juggling flaming swords 🔥. I've been there before. This cheat sheet is your brain’s new best friend — just enough code to refresh your memory and keep you shipping like a pro. 🚀

📑 Table of Contents

If you learn how to use all of these hooks perfectly the next time your PR get's reviewed the team lead's mouth would be dropped. Jokes aside, let's learn.

🟢 Basic Hooks (must-know)

useState - your mini storage box (or getters and setters without tons of boilerplate)

This is where it all starts. useState lets your component "remember" things between renderers. Think of it as a little box where you can store values.

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

<button onClick={() => setCount(count + 1)}>
  You clicked {count} times
</button>
Enter fullscreen mode Exit fullscreen mode

Whe you call setCount, React re-renders the component with the new value.

Usage API:

const [value, setValue] = useState(initialValue);  // 💡 Tip: You can pass a function as initialValue for expensive calculations
Enter fullscreen mode Exit fullscreen mode
  • value → current state
  • setValue → function to update it
  • initialValue → starting value

useEffect - sife effect manager.

At this point is where in almost all of the tutorials online you would hear "now this is where it gets a bit hacky", but don't worry, just with a bit of practice this hooks becomes like a second nature.
Want to fetch data, set up a subscription, or mess with document.title? That's useEffect. It runs after the component renders.

useEffect(() => {
  console.log("Component mounted or updated!");

  return () => {
    console.log("Cleanup before unmount or next run");
  };
}, [/* dependencies here */]);
Enter fullscreen mode Exit fullscreen mode

Add dependencies in the array ([userId]) to control when it runs. Leave it empty ([]) if you want it only once on mount.

Usage API:

useEffect(() => {
  // side effect
  return () => { /* cleanup */ }
}, [dependencies]);
Enter fullscreen mode Exit fullscreen mode
  • Runs after every render unless you control it with dependencies
  • Empty array ([]) → run only once
  • [dep1, dep2] → run when these change

useContext - no more prop-drilling pain

I've tought a lot whether should i place this hook here or in the "advanced" section, as I rarely see anybody use it in their personal projects. If you do - I'm really impressed by your React skills, if not - this hook would take you far.
Tired of passing props down three... four... five levels deep? useContext lets you read from a context directly.

const ThemeContext = React.createContext("light");

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar() {
  const theme = useContext(ThemeContext);
  return <button className={theme}>I’m {theme} mode</button>;
}
Enter fullscreen mode Exit fullscreen mode

Use it when multiple components need the same data (theme, user, language, etc.)

Usage API

const value = useContext(MyContext);
Enter fullscreen mode Exit fullscreen mode
  • MyContext → the context object you created with React.createContext.
  • value → whatever the nearest Provider is giving you

⚡ Advanced Hooks (for optimization & complex state)

useReducer - the state machine

Now this is where the senior level react devs get separated from the juniors. Personally, whenever i see that somebody uses this hook i get goosebumps and give their repo a star. :D

When the state logic gets complicated, useReducer steps in. It's like useState but with superpowers. Perfect for forms, complex toggles, or anything with multiple actions.

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

const [state, dispatch] = useReducer(reducer, { count: 0 });

<button onClick={() => dispatch({ type: "increment" })}>
  {state.count}
</button>
Enter fullscreen mode Exit fullscreen mode

Usage API:

const [state, dispatch] = useReducer(reducerFn, initialState);
Enter fullscreen mode Exit fullscreen mode
  • state → current state
  • dispatch → function to send actions
  • reducerFn(state, action) → decides how state changes

useCallback - memorized functions

Please, please, I beg you - use this instead of going trough every single component in your project just to rename a function. 😭

If you keep passing the same function dodwn to child components and triggering re-renders, useCallback saves the day by memorizing it.

const memoizedHandler = useCallback(() => {
  console.log("Runs only when deps change");
}, [dependency]);
Enter fullscreen mode Exit fullscreen mode

Usage API:

const memoizedFn = useCallback(fn, [dependencies]);
Enter fullscreen mode Exit fullscreen mode
  • Returns the same function instance unless dependencies change
  • Great for performance tuning

useMemo - memorized values

Note: ts really helps with optimisations, dive even deeper into it, you won't regret - https://react.dev/reference/react/useMemo

Expensive calculations? Wrap them in useMemo so they don't run every render.

const expensiveValue = useMemo(() => heavyCalculation(data), [data]);
Enter fullscreen mode Exit fullscreen mode

Usage API:

const memoizedValue = useMemo(calcFn, [dependencies]);
Enter fullscreen mode Exit fullscreen mode
  • Only recalculates if dependencies change
  • Think of it as a cached result

useRef - the persistent box

ChatGPT's favourite hook when it comes to more eye-catching visuals :D

Need a value that sticks around but doesn't change re-renders? That's useRef. Perfect for acessing DOM elements or keeping track of mutable stuff.

const inputRef = useRef(null);

<input ref={inputRef} />
<button onClick={() => inputRef.current.focus()}>
  Focus input
</button>
Enter fullscreen mode Exit fullscreen mode

Usage API:

const ref = useRef(initialValue);
Enter fullscreen mode Exit fullscreen mode
  • ref.current → mutable value (DOM node or custom value)

useImperativeHandle - custom ref API

Sometimes you want a parent to call methods on a child. This hook lets you expose a custom API when using forwardRef.

useImperativeHandle(ref, () => ({
  focus: () => inputRef.current.focus()
}));
Enter fullscreen mode Exit fullscreen mode

Usage API:

useImperativeHandle(ref, () => customObject, [dependencies]);
Enter fullscreen mode Exit fullscreen mode
  • Used with forwardRef
  • Lets parents call methods like childRef.current.doSomething()

useLayoutEffect - sync effect

Like useEffect, but runs synchronously after DOM mutations (before the browser paints). Useful for measuring layout or scrolling.

useLayoutEffect(() => {
  console.log("DOM is ready, before paint");
}, []);
Enter fullscreen mode Exit fullscreen mode

Usage API:

useLayoutEffect(effectFn, [dependencies]);
Enter fullscreen mode Exit fullscreen mode
  • Blocks painting until it's done (⚠️ use carefully)

useDebugValue – dev tools helper

Used in custom hooks to label values in React DevTools. Not for production code, just debugging.

function useFriendStatus(friendID) {
  const isOnline = useSomeCustomHook(friendID);
  useDebugValue(isOnline ? "Online" : "Offline");
  return isOnline;
}
Enter fullscreen mode Exit fullscreen mode

Usage API:

useDebugValue(value, formatFn?);
Enter fullscreen mode Exit fullscreen mode
  • Shows extra info in React DevTools

These hooks are your toolbox for performance & advanced state. You won’t use all of them daily, but knowing they exist = huge time saver.

🧪 React 18+ Hooks (new & shiny)

useId – unique IDs without headaches

Needa stable ID for accessibility or forms? useId generates unique IDs that won't change across renders.

const id = useId();

<label htmlFor={id}>Name</label>
<input id={id} />
Enter fullscreen mode Exit fullscreen mode

Usage API:

const id = useId();
Enter fullscreen mode Exit fullscreen mode
  • Returns a stable, uniqe string
  • Perfect for accessibility (htmlFor, aria-* attributes)

useTransition – smooth state updates

Mark updates as "non-blocing" to keep the UI responsive during heavy renders.

const [isPending, startTransition] = useTransition();

startTransition(() => {
  setList(hugeNewList);
});

isPending && <Spinner />
Enter fullscreen mode Exit fullscreen mode

Usage API:

const [isPending, startTransition] = useTransition();
Enter fullscreen mode Exit fullscreen mode
  • isPending → true while transition is happening
  • startTransition(callback) → wrap updates that can be delayed

useDeferredValue - defer slow updates

Smooth out your UI by deferring non-critical updates.

const deferredSearch = useDeferredValue(searchQuery);

useEffect(() => {
  fetchData(deferredSearch);
}, [deferredSearch]);
Enter fullscreen mode Exit fullscreen mode

Usage API:

const deferredValue = useDeferredValue(value);
Enter fullscreen mode Exit fullscreen mode
  • Returns a slower-updating version of a value
  • Useful for large lists, autocomplete, or filtering

useSyncExternalStore - safe external subscriptions

Subscribe to external stores like Redux or custom stores safely, with React 18’s concurrent rendering.

const state = useSyncExternalStore(
  store.subscribe,
  store.getSnapshot
);
Enter fullscreen mode Exit fullscreen mode

Usage API:

const state = useSyncExternalStore(subscribeFn, getSnapshotFn);
Enter fullscreen mode Exit fullscreen mode
  • subscribeFn → called to listen for changes
  • getSnapshotFn → returns the current state
  • Handles concurrent updates safely

useInsertionEffect – style injection before paint

Mostly for CSS-in-JS libraries. Runs before DOM mutations, ensuring styles are applied before rendering.

useInsertionEffect(() => {
  injectStyles(".btn { color: red }");
}, []);
Enter fullscreen mode Exit fullscreen mode

Usage API:

useInsertionEffect(effectFn, [dependencies]);
Enter fullscreen mode Exit fullscreen mode
  • Runs synchronously before paint
  • Great for styling libraries that need to inject CSS

🛠️ Custom Hooks – your secret weapon

Custom hooks are basically functions that use other hooks. They let you reuse logic across components without repeating yourself. Think of them as mini React utilities that you can plug in anywhere.

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

// Usage in a component
function App() {
  const [isOpen, toggleOpen] = useToggle(false);
  return <button onClick={toggleOpen}>{isOpen ? "Open" : "Closed"}</button>;
}
Enter fullscreen mode Exit fullscreen mode

Usage API:

const [value, toggle] = useToggle(initialValue);
Enter fullscreen mode Exit fullscreen mode
  • value → current state
  • toggle() → flips state from true → false or false → true

Example: useLocalStorage – state that survives refreshes

function useLocalStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(() => {
    return JSON.parse(localStorage.getItem(key)) ?? initialValue;
  });

  const setValue = (value) => {
    setStoredValue(value);
    localStorage.setItem(key, JSON.stringify(value));
  };

  return [storedValue, setValue];
}

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

⬆ Back to top

Wrap-Up – your React Hooks cheat sheet

And that’s a wrap! 🎉

You’ve now got a one-stop reference for all React hooks — from the essentials to the shiny new toys in React 18+. Keep this page handy, because next time someone asks for a “React hook example,” you’ll just wink and say, “Already got it.” 😎

Remember:

  • Basic hooks = your everyday tools (useState, useEffect, useContext)
  • Advanced hooks = performance & complex state wizards (useReducer, useCallback, useMemo, useRef)
  • React 18+ hooks = concurrent rendering magic (useTransition, useDeferredValue, useSyncExternalStore)
  • Custom hooks = your secret weapons to reuse logic like a pro

If this cheat sheet saved you even a minute of Googling, consider buying me a coffee to keep the content flowing: ko-fi.com/deyan_sirakov ☕💖

Now go forth, hook like a hero, and never forget: React hooks are powerful, but your memory doesn’t have to be.

Top comments (0)