Skip to main content

Command Palette

Search for a command to run...

⚛️ React Hooks: The Complete Guide for Modern React Developers

⚛️ React Hooks

Published
4 min read
⚛️ React Hooks: The Complete Guide for Modern React Developers

React Hooks transformed the entire React ecosystem.
Before Hooks, developers relied heavily on class components, lifecycle methods, and complex patterns.

Hooks changed everything by giving functions the power of state, lifecycle, and logic reuse.

In this blog, you’ll learn:

✔ What Hooks are
✔ Why they exist
✔ Every important built-in Hook
✔ Practical examples
✔ Best practices
✔ Common mistakes

Let’s dive in 👇


🧠 What Are React Hooks?

Hooks are special functions that let you “hook into” React features
like state, lifecycle methods, refs, memoization, and context — all inside function components.

Examples:

  • useState → manage local state

  • useEffect → perform side effects

  • useContext → use global state

  • useRef → refer to DOM or store values

  • useCallback / useMemo → optimize performance

Hooks make React code:

✔ Cleaner
✔ Reusable
✔ Easier to understand
✔ Function-based (no classes needed)


🎯 Why React Hooks?

Earlier problems before Hooks:

❌ Class components were bulky
❌ Logic sharing required HOCs or render props
❌ Complex lifecycle methods
❌ “this” keyword confusion

Hooks solved all these.


🪝 Types of React Hooks

React Hooks are divided into:

  1. Basic Hooks

  2. Additional Hooks

  3. Performance Hooks

  4. Custom Hooks

Let’s explore each one with examples.


1️⃣ useState — Manage Local State

import { useState } from "react";

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

  return (
    <>
      <h2>{count}</h2>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </>
  );
}

✔ Simple state
✔ Rerenders UI when updated


2️⃣ useEffect — Handle Side Effects

Use for:

  • API calls

  • Event listeners

  • Subscriptions

  • Timers

  • DOM updates

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

  return () => {
    console.log("Cleanup on unmount");
  };
}, []);

The dependency array [] controls when effects run.


3️⃣ useContext — Access Global State

const theme = useContext(ThemeContext);

Replaces prop drilling.


4️⃣ useRef — Store Values or Access DOM

const inputRef = useRef();

function focusInput() {
  inputRef.current.focus();
}

Does not trigger re-renders.


5️⃣ useReducer — For Complex State Logic

Better than useState when:

  • Many state transitions

  • Complex logic

  • Multiple related values

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

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

6️⃣ useCallback — Prevent Unnecessary Re-renders

const handleClick = useCallback(() => {
  console.log("Clicked");
}, []);

Useful when passing functions to child components.


7️⃣ useMemo — Memoize Expensive Calculations

const result = useMemo(() => heavyFunction(value), [value]);

Prevents recalculating expensive logic.


8️⃣ useLayoutEffect — Runs Before Browser Paint

Similar to useEffect, but synchronous.

Use only when necessary (e.g., measuring DOM size).


9️⃣ useImperativeHandle — Customize Refs for Child Components

Used with forwardRef.

useImperativeHandle(ref, () => ({
  focus: () => inputRef.current.focus(),
}));

🔥 Custom Hooks — Your Own Reusable Logic

Example: Fetch API Hook

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

  useEffect(() => {
    fetch(url).then(res => res.json()).then(setData);
  }, [url]);

  return data;
}

Use in any component:

const users = useFetch("/api/users");

🚀 Real-Life Example: Dark Mode Using Hooks

function App() {
  const [theme, setTheme] = useState("light");

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

  return (
    <>
      <h2>Theme: {theme}</h2>
      <button onClick={() => setTheme("dark")}>Dark Mode</button>
      <button onClick={() => setTheme("light")}>Light Mode</button>
    </>
  );
}

⚠️ Rules of Hooks (IMPORTANT)

React enforces two rules:

1️⃣ Only call Hooks at the top level

❌ No loops
❌ No conditions
❌ No nested functions

2️⃣ Only call Hooks inside React components or custom hooks

❌ Not inside regular JS functions
❌ Not outside components


🧠 Common Mistakes

❌ Using useEffect without dependency array
❌ Forgetting cleanup functions
❌ Using too many states instead of useReducer
❌ Overusing useMemo & useCallback
❌ Updating refs expecting re-renders


🏆 When to Use Which Hook?

HookBest For
useStateSimple state
useEffectSide effects
useContextGlobal state
useReducerComplex logic
useRefDOM or persistent values
useCallbackOptimizing functions
useMemoOptimizing values
Custom HooksReuse logic

🎉 Final Thoughts

React Hooks simplified everything about React.

With them, function components handle:

✔ State
✔ Lifecycle
✔ Side effects
✔ Performance optimizations
✔ Shared logic

Hooks make apps faster, cleaner, and easier to maintain.