An Overview of Widely Used ReactJS Hooks

2 min read

An Overview of Widely Used ReactJS Hooks

ReactJS introduced Hooks in version 16.8, revolutionizing the way developers write functional components. Hooks allow you to use state, lifecycle methods, and other React features in functional components, making code more concise, reusable, and easier to maintain. In this article, we’ll explore some of the most widely used React hooks with detailed explanations and examples.

1. useState

The useState hook is the most commonly used hook in React. It allows you to add state to functional components.

Example: Counter App

import React, { useState } from "react";

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

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

What it does: useState initializes the state variable count with 0. The setCount function updates its value.

2. useEffect

The useEffect hook lets you perform side effects such as data fetching, DOM manipulation, or subscriptions.

Example: Fetching Data

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

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

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/posts")
      .then((response) => response.json())
      .then((json) => setData(json));
  }, []); // Empty dependency array runs the effect once, like componentDidMount

  return (
    <ul>
      {data.map((item) => (
        <li key={item.id}>{item.title}</li>
      ))}
    </ul>
  );
}

What it does: Runs a side effect (data fetching) when the component mounts.

3. useContext

The useContext hook provides a way to access data from React’s Context API, avoiding the need for prop drilling.

Example: Theme Context

import React, { createContext, useContext } from "react";

const ThemeContext = createContext("light");

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

function ThemedComponent() {
  const theme = useContext(ThemeContext);
  return <p>The current theme is {theme}.</p>;
}

What it does: Fetches the theme value from ThemeContext.

4. useRef

The useRef hook creates a reference to a DOM element or stores mutable values that persist across renders without causing re-renders.

Example: DOM Manipulation

import React, { useRef } from "react";

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

  const focusInput = () => {
    inputRef.current.focus();
  };

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

What it does: Directly accesses the DOM element using inputRef.

5. useReducer

The useReducer hook is useful for managing complex state logic. It’s an alternative to useState for situations where state transitions are complex or involve multiple sub-values.

Example: Counter with Reducer

import React, { 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:
      throw new Error();
  }
}

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

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

What it does: Manages state transitions using the reducer function.

6. useMemo

The useMemo hook is used to optimize performance by memoizing expensive computations, avoiding unnecessary recalculations.

Example: Expensive Calculation

import React, { useState, useMemo } from "react";

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

function App() {
  const [count, setCount] = useState(1);
  const [multiplier, setMultiplier] = useState(2);

  const memoizedResult = useMemo(() => ExpensiveCalculation({ num: multiplier }), [multiplier]);

  return (
    <div>
      <h1>Result: {memoizedResult}</h1>
      <button onClick={() => setCount(count + 1)}>Re-render</button>
      <button onClick={() => setMultiplier(multiplier + 1)}>Change Multiplier</button>
    </div>
  );
}

What it does: Prevents recalculating ExpensiveCalculation unless multiplier changes.

7. useCallback

The useCallback hook memoizes functions, preventing unnecessary re-creations during renders, especially useful with React.memo.

Example: Memoized Callback

import React, { useState, useCallback } from "react";

function Child({ increment }) {
  console.log("Child rendered");
  return <button onClick={increment}>Increment</button>;
}

const MemoizedChild = React.memo(Child);

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

  const increment = useCallback(() => setCount((prev) => prev + 1), []);

  return (
    <div>
      <p>Count: {count}</p>
      <MemoizedChild increment={increment} />
    </div>
  );
}

What it does: Prevents increment from being re-created on every render.

Conclusion

ReactJS hooks have transformed the way developers write functional components, making code more elegant and easier to understand. From managing state with useState to optimizing performance with useMemo and useCallback, each hook serves a specific purpose.

🤞 Never miss a story from us, get weekly updates to your inbox!