React hooks are JavaScript functions that enable you to manage state and side effects in functional components, and they are a critical part of building modern React applications. Before hooks, React only allowed state management through class components, but hooks allow us to use state, lifecycle methods, and other features in functional components.

Here’s an introduction to the main React hooks:


1. React Hook #1 useState

  • Purpose: Allows you to add state to functional components.
  • Usage: It returns an array with two values:
    1. state value (the current state value)
    2. function to update state.

Example:

import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); // Initial state is 0

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

When to Use: Use useState to handle local component state.


2. React Hook #2 useEffect

  • Purpose: Handles side effects in functional components. This includes tasks like data fetching, subscriptions, and manually changing the DOM.
  • Usage: The hook runs after the render phase and can run either once, on every render, or based on specific dependencies.

Example:

import { useEffect, useState } from 'react';

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

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => setData(data));
  }, []); // Empty array means this effect runs only once after the first render

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

When to Use: Use useEffect for operations like:

  • Fetching data from an API.
  • Setting up subscriptions or event listeners.
  • Performing cleanup (e.g., clearing timers, removing event listeners).

3. React Hook #3 useContext

  • Purpose: Provides a way to consume values from React’s Context API (a way to pass data through the component tree without having to pass props manually at every level).
  • Usage: You pass a Context object to useContext to access its value.

Example:

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

const UserContext = createContext();

function UserProfile() {
  const user = useContext(UserContext);
  return <div>Hello, {user.name}!</div>;
}

function App() {
  const user = { name: 'John Doe' };

  return (
    <UserContext.Provider value={user}>
      <UserProfile />
    </UserContext.Provider>
  );
}

When to Use: Use useContext when you need to share values (e.g., theme, user info) between components without prop drilling.


4. React Hook #4 useReducer

  • Purpose: A more advanced state management hook, used when state logic is complex (e.g., managing multiple related state values or handling complex actions).
  • Usage: Works similarly to useState, but instead of setting the state directly, you dispatch actions to a reducer function that calculates the next state based on the current state and action.

Example:

import { 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:
      return state;
  }
}

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

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
    </div>
  );
}

When to Use: Use useReducer when you have complex state logic that involves multiple sub-values or actions that need to be handled in a more organized way than useState.


5. React Hook #5 useCallback

  • Purpose: Returns a memoized version of the function, which only changes if one of the dependencies has changed. This is useful to avoid re-creating functions unnecessarily on each render.
  • Usage: Ideal when passing functions to child components that depend on the function not changing unless certain values change.

Example:

import { useState, useCallback } from 'react';

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

  const handleClick = useCallback(() => {
    console.log('Count clicked:', count);
  }, [count]); // Memoized function, updates only when `count` changes

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

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

When to Use: Use useCallback when passing functions to child components or when you need to prevent unnecessary re-renders due to changing functions.


6. React Hook #6 useMemo

  • Purpose: Returns a memoized value. This hook helps in optimizing expensive computations by recalculating the result only when the dependencies change.
  • Usage: Useful when you have calculations that are expensive and only need to be re-executed when certain values change.

Example:

import { useMemo } from 'react';

function ExpensiveCalculation({ data }) {
  const computedValue = useMemo(() => {
    return data.reduce((sum, num) => sum + num, 0); // Expensive calculation
  }, [data]); // Only recompute if `data` changes

  return <div>{computedValue}</div>;
}

When to Use: Use useMemo to optimize performance by memoizing expensive computations or values that don’t need to be recalculated on every render.


7. React Hook #7 useRef

  • Purpose: Returns a mutable ref object that persists across renders. It’s often used to reference DOM elements or store mutable variables that don’t cause re-renders when updated.
  • Usage: It doesn’t trigger re-renders, so it’s useful for things like focus management, measuring DOM elements, or storing values across renders.

Example:

import { useRef } from 'react';

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

  const focusInput = () => {
    inputRef.current.focus(); // Directly interacting with DOM
  };

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

When to Use: Use useRef to interact with DOM elements directly or store mutable values across renders without triggering a re-render.

Summary of React Hooks

  • useState: For simple state management.
  • useEffect: For side effects (e.g., data fetching).
  • useContext: For consuming global state via React Context.
  • useReducer: For managing complex state logic.
  • useRef: For accessing DOM or storing mutable values.
  • useMemo: For memoizing expensive calculations.
  • useCallback: For memoizing functions.
  • useLayoutEffect: For DOM measurements or adjustments before painting.
  • useImperativeHandle: For customizing ref behavior with forwardRef.
  • useDebugValue: For debugging custom hooks in React DevTools.

These hooks empower you to write clean, efficient, and maintainable functional components in React.

Official Documentation – Built-in React Hooks – React

Conclusion

In this guide, we covered React hooks that help you manage state, side effects, context, and more in functional components. Whether you’re managing simple states with useState, handling side effects with useEffect, or optimizing performance with useMemo and useCallback, hooks make your React code cleaner and more efficient.

By understanding and using these hooks, you can create robust, maintainable React applications with improved performance.

Categorized in:

React,