Essential React Hooks & Practical Use Cases

What Are React Hooks? Functions that let you use React features in functional components without classes. 7 Essential Hooks 1. useState What it does: keeps track of values that can change in your app // e.g. 1: Basic state management const [count, setCount] = useState(0); // e.g. 2: Form inputs const [name, setName] = useState(''); When to use: Storing form input values Toggling UI states (open/closed) Tracking simple values (counters, flags) 2. useEffect What it does: helps us run code when things change (or when a component first loads) // e.g. 1: Run once on mount (empty dependencies) useEffect(() => { // Setup code return () => { /* Cleanup code */ }; }, []); // e.g. 2: Run when dependencies change useEffect(() => { document.title = `${count} new messages`; }, [count]); When to use: Data fetching Subscriptions/event listeners DOM manipulation Syncing with external systems 3. useContext What it does: allows multiple components to share the same data without passing it manually // Access theme from anywhere in component tree const theme = useContext(ThemeContext); When to use: Accessing global state (themes, user data) Avoiding prop drilling through many components When multiple components need the same data 4. useRef What it does: helps reference an element without causing unnecessary re-renders // e.g. 1: DOM element reference const inputRef = useRef(null); inputRef.current.focus(); // e.g. 2: Value persistence between renders const prevCountRef = useRef(); When to use: Accessing DOM elements Storing previous values Holding values that shouldn't trigger re-renders Managing timers/intervals 5. useReducer What it does: Manages complex state logic const [state, dispatch] = useReducer(reducer, initialState); dispatch({ type: 'increment' }); When to use: Complex state with multiple sub-values When next state depends on previous state When state transitions have business logic When actions cause multiple state updates 6. useMemo What it does: expensive calculations to avoid recomputing them unnecessarily const expensiveValue = useMemo(() => { return computeExpensiveValue(data); }, [data]); When to use: Optimizing performance-heavy calculations Preventing unnecessary computations 7. useCallback What it does: Memoizes functions so they don’t get recreated every render const handleClick = useCallback(() => { console.log('Clicked!'); }, []); When to use: Preventing unnecessary re-renders in child components Avoiding function recreation on every render Custom Hooks Create your own hooks to reuse logic between components: // Extract reusable logic function useWindowSize() { const [size, setSize] = useState({ width: window.innerWidth, height: window.innerHeight }); // Event handling + cleanup in one hook useEffect(() => { const handleResize = () => setSize({ width: window.innerWidth, height: window.innerHeight }); window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); return size; } Rules of Hooks Only call at top level (no conditions/loops) Only call from React functions Name custom hooks with "use" prefix Quick Tips Use useState for simple state, useReducer for complex state Don't forget cleanup functions in useEffect Optimize renders with useMemo and useCallback Create custom hooks to share logic, not just for reuse Use useImperativeHandle to expose methods from child components to parents. Use useLayoutEffect when updates need to happen before the browser paints. Use useDebugValue to add labels to custom hooks for easier debugging in React DevTools.

Feb 26, 2025 - 00:03
 0
Essential React Hooks & Practical Use Cases

What Are React Hooks?

Functions that let you use React features in functional components without classes.

7 Essential Hooks

1. useState

What it does: keeps track of values that can change in your app

// e.g. 1: Basic state management
const [count, setCount] = useState(0);

// e.g. 2: Form inputs
const [name, setName] = useState('');

When to use:

  • Storing form input values
  • Toggling UI states (open/closed)
  • Tracking simple values (counters, flags)

2. useEffect

What it does: helps us run code when things change (or when a component first loads)

// e.g. 1: Run once on mount (empty dependencies)
useEffect(() => {
  // Setup code
  return () => { /* Cleanup code */ };
}, []);

// e.g. 2: Run when dependencies change
useEffect(() => {
  document.title = `${count} new messages`;
}, [count]);

When to use:

  • Data fetching
  • Subscriptions/event listeners
  • DOM manipulation
  • Syncing with external systems

3. useContext

What it does: allows multiple components to share the same data without passing it manually

// Access theme from anywhere in component tree
const theme = useContext(ThemeContext);

When to use:

  • Accessing global state (themes, user data)
  • Avoiding prop drilling through many components
  • When multiple components need the same data

4. useRef

What it does: helps reference an element without causing unnecessary re-renders

// e.g. 1: DOM element reference
const inputRef = useRef(null);
inputRef.current.focus();

// e.g. 2: Value persistence between renders
const prevCountRef = useRef();

When to use:

  • Accessing DOM elements
  • Storing previous values
  • Holding values that shouldn't trigger re-renders
  • Managing timers/intervals

5. useReducer

What it does: Manages complex state logic

const [state, dispatch] = useReducer(reducer, initialState);
dispatch({ type: 'increment' });

When to use:

  • Complex state with multiple sub-values
  • When next state depends on previous state
  • When state transitions have business logic
  • When actions cause multiple state updates

6. useMemo

What it does: expensive calculations to avoid recomputing them unnecessarily

const expensiveValue = useMemo(() => {
  return computeExpensiveValue(data);
}, [data]);

When to use:

  • Optimizing performance-heavy calculations
  • Preventing unnecessary computations

7. useCallback

What it does: Memoizes functions so they don’t get recreated every render

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

When to use:

  • Preventing unnecessary re-renders in child components
  • Avoiding function recreation on every render

Custom Hooks

Create your own hooks to reuse logic between components:

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

  // Event handling + cleanup in one hook
  useEffect(() => {
    const handleResize = () => setSize({ width: window.innerWidth, height: window.innerHeight });
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return size;
}

Rules of Hooks

  1. Only call at top level (no conditions/loops)
  2. Only call from React functions
  3. Name custom hooks with "use" prefix

Quick Tips

  • Use useState for simple state, useReducer for complex state
  • Don't forget cleanup functions in useEffect
  • Optimize renders with useMemo and useCallback
  • Create custom hooks to share logic, not just for reuse
  • Use useImperativeHandle to expose methods from child components to parents.
  • Use useLayoutEffect when updates need to happen before the browser paints.
  • Use useDebugValue to add labels to custom hooks for easier debugging in React DevTools.