🛠️ Understanding React Hooks: A Simple Guide

Victor AdeobaVictor Adeoba
4 min read

React hooks make it easier to manage state, handle side effects, and share data between components without needing to write complex code. In this guide, we’ll break down six common hooks: useState, useMemo, useCallback, useRef, useEffect, and useContext. Let’s dive in! 🚀

Prerequisites

To follow along, you should have a basic understanding of:

  • JavaScript: Knowing about variables, functions, and arrays will help a lot.

  • React: You should be familiar with components and props.

If you’re comfortable with these basics, you’re all set!

🚀 useState — Managing Component State

useState lets you add and manage state in your functional components.

How It Works:

  • It returns an array with two items:

    1. The current state.

    2. A function to update the state.

import { useState } from 'react';

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

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increase</button>
    </div>
  );
}

Explanation:

  • useState(0) sets the initial count to 0.

  • setCount updates the count when the button is clicked.

🚀 useMemo — Memorizing Expensive Calculations

useMemo is used to memorize the result of expensive functions(functions that might slow down the app) so they don’t run every time the component re-renders.

How It Works:

  • Runs the function only if its dependencies change.

  • Useful for heavy calculations that don’t need to re-run unless certain data changes.

import { useMemo } from 'react';

function heavyFunction({ num }) { // destructing the props
  const doubled = useMemo(() => {
    console.log('Calculating..., ⚠️I will slow down the page');
    return num * 2;
  }, [num]);

  return <p>Doubled: {doubled}</p>;
// useMemo has been used to memorize the function so it doesn't rerender unless the num value changes
}

Explanation:

  • useMemo only recalculates if num changes, saving time for heavy calculations.

🚀 useCallback — Memorizing Functions

useCallback is similar to useMemo but for functions. It prevents child components from re-rendering unnecessarily when you pass functions as props.

How It Works:

  • Memorizes the function until its dependencies change.
import { useCallback } from 'react';

function Button({ onClick }) {
  console.log('Button rendered!');
  return <button onClick={onClick}>Click Me</button>;
}

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

  return <Button onClick={handleClick} />;
}

Explanation:

  • handleClick is memorized and doesn’t get recreated on every re-render.

  • Button won’t re-render unless handleClick actually changes.

🚀 useRef — Accessing DOM Elements and Persisting Values

useRef lets you access DOM elements directly or persist values across renders without causing re-renders.

How It Works:

  • Returns a mutable object with a .current property.
import { useRef } from 'react';

function TextInput() {
  const inputRef = useRef(null);

  const focusInput = () => {
    inputRef.current.focus();  // Focuses the input element directly
  };

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={focusInput}>Focus Input</button>
    </div>
  );
}

Explanation:

  • useRef stores the input element in inputRef.current without causing re-renders.

useEffect — Handling Side Effects

useEffect lets you run side effects in your components, like fetching data or updating the DOM.

How It Works:

  • Runs the function after the component renders.

  • You can control when it runs using a dependency array.

import { useEffect, useState } from 'react';

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

  useEffect(() => {
    fetch('https://api.bottom.com/data')
      .then((response) => response.json())
      .then((data) => setData(data));
  }, []);  // Runs only once when the component renders

  return <div>Data: {data ? JSON.stringify(data) : 'Loading...'}</div>;
}

Explanation:

  • The empty array ([]) makes useEffect run only once when the component mounts.

🚀 useContext — Sharing Data Across Components

useContext makes it easy to share data between components without prop drilling (passing props through multiple levels).

How It Works:

  • Uses a Context Provider to wrap components and a Consumer to access data.
import { useContext, createContext } from 'react';

const ThemeContext = createContext('light');

function Child() {
  const theme = useContext(ThemeContext);
  return <p>Current Theme: {theme}</p>;
}

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

Explanation:

  • useContext directly accesses the theme value ("dark"), skipping prop drilling.

Conclusion

We have come to the end of this article, I am confident enough that you have finally understood what React Hooks are and when you need to use them.

Pat yourself in back for coming this far, you are on the journey of becoming one of the best React developer in the world, Meta doesn't know you are coming!.

🛠️Keep building

0
Subscribe to my newsletter

Read articles from Victor Adeoba directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Victor Adeoba
Victor Adeoba