Back to articles

Mastering React Hooks: A Practical Guide with Real-World Examples

AuthorMajd Muhtaseb11/24/202510 minutes

Introduction

React Hooks revolutionized functional components by enabling them to use state and other React features without writing classes. This guide provides a practical overview of commonly used hooks and their applications.

useState

The useState hook allows you to add state to functional components.

import React, { useState } from 'react';

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

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

export default Counter;

This example demonstrates a simple counter component. useState(0) initializes the count state variable to 0. The setCount function is used to update the state, triggering a re-render.

useEffect

The useEffect hook lets you perform side effects in functional components. These can include data fetching, DOM manipulation, or setting up subscriptions.

import React, { useState, useEffect } from 'react';

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

  useEffect(() => {
    async function fetchData() {
      const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
      const json = await response.json();
      setData(json);
    }

    fetchData();

    // Cleanup function (optional)
    return () => {
      // Perform cleanup here (e.g., cancel subscriptions)
    };
  }, []); // The empty dependency array ensures the effect runs only once on mount.

  if (!data) {
    return <p>Loading...</p>;
  }

  return (
    <div>
      <p>Title: {data.title}</p>
    </div>
  );
}

export default Example;

This example fetches data from an API endpoint when the component mounts. The empty dependency array [] ensures that the effect runs only once. A cleanup function can optionally be returned to prevent memory leaks.

useContext

The useContext hook allows you to access values from React Context without needing to use a Consumer component.

import React, { useContext } from 'react';

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

function ThemedButton() {
  const theme = useContext(ThemeContext);

  return (
    <button style={{ backgroundColor: theme === 'dark' ? 'black' : 'white', color: theme === 'dark' ? 'white' : 'black' }}>
      Themed Button ({theme})
    </button>
  );
}

export default ThemedButton;

This example demonstrates using useContext to access the current theme value.

useCallback

The useCallback hook memoizes a function. This can improve performance by preventing unnecessary re-renders of child components that receive the function as a prop.

import React, { useCallback } from 'react';

function MyComponent({ onButtonClick }) {
  return (
    <button onClick={onButtonClick}>Click Me</button>
  );
}

function ParentComponent() {
  const handleClick = useCallback(() => {
    console.log('Button clicked!');
  }, []); // Empty dependency array - function is only created once

  return (
    <MyComponent onButtonClick={handleClick} />
  );
}

export default ParentComponent;

In this example, handleClick is only created once, so MyComponent will only re-render if its own props change.

useMemo

The useMemo hook memoizes the result of a calculation. Like useCallback, this helps optimize performance.

import React, { useMemo } from 'react';

function ExpensiveCalculation({ a, b }) {
  const result = useMemo(() => {
    // Simulate a very expensive calculation
    console.log('Calculating...');
    let i = 0;
    while (i < 100000000) {
      i++;
    }
    return a + b;
  }, [a, b]); // Only recalculate if a or b changes

  return (
    <div>
      Result: {result}
    </div>
  );
}

export default ExpensiveCalculation;

result will only be recalculated if a or b changes. Otherwise, the cached value is returned.

Conclusion

React Hooks provide a powerful and concise way to manage state and side effects in functional components. By understanding and utilizing these hooks effectively, you can write cleaner, more maintainable, and performant React applications.