React introduced hooks to bring state management, side effects, and performance optimizations to functional components. Among the most important ones are useEffect, useReducer, and useMemo.

Let’s explore them in detail with icons, syntax, examples, and best practices.

⚡ useEffect – Side Effects

🛠 What does it do?

📑 Syntax

useEffect(() => {
  // effect logic here

  return () => {
    // cleanup logic here (optional)
  };
}, [dependencies]);

📌 Explanation of Dependencies

🖼 Example

import { useState, useEffect } from "react";

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

  useEffect(() => {
    const timer = setInterval(() => setCount(c => c + 1), 1000);

    return () => clearInterval(timer); // cleanup
  }, []);

  return <h1>Time: {count}s</h1>;
}

✅ Best Use Cases

🎛 useReducer – Complex State Management

🛠 What does it do?

📑 Syntax

const [state, dispatch] = useReducer(reducer, initialState);

📌 Reducer Function

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

🖼 Example

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:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <>
      <h1>Count: {state.count}</h1>
      <button onClick={() => dispatch({ type: "increment" })}>+</button>
      <button onClick={() => dispatch({ type: "decrement" })}>-</button>
    </>
  );
}

✅ Best Use Cases

🚀 useMemo – Performance Optimization

🛠 What does it do?

📑 Syntax

const memoizedValue = useMemo(
  () => computeExpensiveValue(a, b),
  [a, b]
);

🖼 Example

import { useState, useMemo } from "react";

function ExpensiveCalculation(num) {
  console.log("Calculating...");
  let result = 0;
  for (let i = 0; i < 1000000000; i++) {
    result += num;
  }
  return result;
}

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

  const calculation = useMemo(() => ExpensiveCalculation(number), [number]);

  return (
    <>
      <h1>Calculation: {calculation}</h1>
      <button onClick={() => setCount(c => c + 1)}>Re-render {count}</button>
      <button onClick={() => setNumber(n => n + 1)}>Increase Number</button>
    </>
  );
}

✅ Best Use Cases

Hook 🔍 Purpose ⏳ When It Runs 🎯 Best Use Case ⚠️ Pitfalls
⚡ useEffect Handle side effects (API calls, timers, subscriptions, DOM updates) After render (depends on dependency array) Data fetching, event listeners, intervals, and cleanup Infinite loops if the dependency array is wrong
🎛 useReducer Manage complex state using reducer & actions When dispatch() is called Forms, counters, multi-step state logic Can be overkill for a simple state
🚀 useMemo Cache expensive calculations to improve performance When dependencies change Heavy calculations, derived values Don’t use for every small calculation (can add overhead)

🔑 Key Takeaways

Together, these hooks make React components.