Exploring React Hooks: What Every Developer Should Know

React Hooks are special functions introduced in React 16.8 that allow you to use state and other React features in functional components, which were previously only available in class components.

Because of Hooks, we don’t need classes; Hooks make it simpler to share logic across components, allowing for more reusable and modular code.

Hooks follow specific rules, like being called at the top level of a component, to ensure consistent behavior

useState Hook

useState hook is used to manage state inside a component. It helps developers to create state variable & provides a function which can be used to update that state variable.

Component will get re-rendered whenever the state changes, in this way component always reflects the correct state.

const [statevar, updatestatevar] = useState(initialstate);

Here is a simple example which implement the counter using useState hook :

import React, { useState } from "react";

function Counter() {
    const [count, setCount] = useState(0);
    const increment = () => {
        setCount(count+1);
    }
    return <>
        <div>Count: {count}</div>
        <button onClick={increment}>Increment</button>
    </>
}

useEffect Hook

By using useEffect Hook, you’re instructing React that your component needs to execute some logic after rendering. React will retain the function you provided and invoke it later, once the DOM updates are complete.

In this effect, we set the document title, but we could also perform data fetching or call some other imperative API. Basically useEffect hook lets you perform side effects in function components.

To implement Timer using useEffect hook, you can set up an interval when the component mounts & clean it up when the component unmounts. Here is an example of Timer using useEffect hook –

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

const Timer = () => {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    // Set up the interval
    const interval = setInterval(() => {
      setSeconds(prevSeconds => prevSeconds + 1);
    }, 1000);

    // Cleanup function to clear the interval
    return () => {
      clearInterval(interval);
    };
  }, []); // Empty dependency array to run effect only once

  return (
    <div>
      <h1>Timer</h1>
      <p>Seconds: {seconds}</p>
    </div>
  );
};

export default Timer;

useContext Hook

The useContext hook is used to consume values from a React context. Context provides a way to pass data through the component tree without having to pass props manually at every level. 

By using useContext hook, you can easily access data like themes, user information, or any shared state. This Hook is particularly useful for avoiding “prop drilling” and maintaining a cleaner, more maintainable codebase.

To use it, you simply pass the context object to useContext, and it returns the current value of that context. Let’s explore how useContext works with a simple example –

import React, {useContext} from 'react';

function App() {
    return (
        <ThemeContext.Provider value="dark">
            <Header/>
        </ThemeContext.Provider>
    )
}
function Header() {
    const theme = useContext(ThemeContext);
    return <Header className={theme}>Dark Theme</Header>
}

useRef Hook

The useRef Hook in React allows developers to persist values across renders without causing a re-render when the value changes. Unlike state, updating a useRef value does not trigger a component re-render, making it ideal for cases where you need to store values like previous state values, timers, or DOM elements.

Let’s explore how useRef works with a simple example –

import { useRef } from 'react';
export default function Form() {
    // focusing a text input using useRef

    const inputRef = useRef(null);
    function handleClick() {
        inputRef.current.focus();
    }
    return (
        <>
            <input ref={inputRef}/>
            <button onClick={handleClick}> Focus </button>
        </>
    )
}

Wrapping up

React hooks allows us to manage state, handle side effects, share logic, and interact with the DOM—all within functional components—eliminating the need for classes. In this article, we have seen useState, useEffect, useContext & useRef hooks.

useState allows us to manage the state of the component. useEffect can be used to handle side effects in an element. useContext will enable us to directly access the state without passing the state through components. useRef is used to maintain the state without causing re-renders.