React Hooks - Top7 Most Commonly Used React Hooks for Efficient Component Management

Pranav Bakare - Sep 22 - - Dev Community

Image description

Best Resources -

How to Use React Hooks – A Step-by-Step Guide for Beginners - The Ankur Tyagi

Beginner in React? This post simplifies React Hooks, making it easy for you to understand and implement them in your projects.

favicon theankurtyagi.com

React Hooks revolutionized the way we write React applications by introducing a simpler, more functional way to manage state and lifecycle methods. Here’s a brief guide to some of the most important React Hooks and when to use them:

useState: Manages state within functional components (e.g., form input, toggle buttons).

useEffect: Handles side effects like data fetching or updating the DOM after render (e.g., API calls, subscribing to events).

useContext: Provides a way to pass data across components without prop drilling (e.g., global themes, user authentication).

useReducer: Manages complex state logic and state transitions (e.g., form handling, state with multiple actions).

useMemo: Optimizes performance by memoizing expensive calculations (e.g., filtering large lists, sorting data).

useCallback: Memoizes functions to prevent unnecessary re-renders in child components (e.g., event handler functions passed as props).

useRef: Accesses DOM elements or persists values across renders without causing re-renders (e.g., focusing input fields, storing timer IDs).

1. useState

  • What It Does: Adds state to functional components.
  • When to Use It: For tracking values like form inputs or toggle states.
  • Why It’s Important: Simplifies state management without using class components.

2. useEffect

  • What It Does: Handles side effects like fetching data or updating the DOM after render.
  • When to Use It: For running code after rendering or when a value changes.
  • Why It’s Important: Replaces lifecycle methods like componentDidMount and componentDidUpdate.

3. useContext

  • What It Does: Provides access to shared values across components without prop drilling.
  • When to Use It: For global settings like themes, authentication, or language preferences.
  • Why It’s Important: Simplifies sharing data across deeply nested components.

4. useReducer

  • What It Does: Manages complex state logic by dispatching actions to a reducer function.
  • When to Use It: For handling complex state transitions or multiple related state variables.
  • Why It’s Important: Ideal for form handling and state transitions with predictable changes.

5. useMemo

  • What It Does: Caches the result of an expensive calculation, recalculating only when dependencies change.
  • When to Use It: For expensive computations or rendering large lists that don't need to change frequently.
  • Why It’s Important: Improves app performance by avoiding unnecessary recalculations.

6. useCallback

  • What It Does: Memoizes a function, ensuring it doesn't change between renders unless dependencies change.
  • When to Use It: When passing functions as props to prevent unnecessary re-renders.
  • Why It’s Important: Optimizes performance by stopping child components from re-rendering unnecessarily.

7. useRef

  • What It Does: Provides a mutable reference to a DOM element or value that persists across renders without causing re-renders.
  • When to Use It: For direct DOM manipulation or storing mutable values like timers.
  • Why It’s Important: Allows interaction with the DOM and management of mutable values without re-rendering.

Conclusion:

Mastering these hooks will enhance your ability to write efficient, scalable React applications.
Hooks like useState and useEffect handle fundamental aspects like state and side effects
.
.
.
while hooks like useMemo, useReducer, and useCallback help you manage performance and more complex logic efficiently.

Here’s a detailed explanation of each example of React hooks:

_ 1. useState Hook_
The useState hook is used to add and manage state in a functional component.

Example:

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;

Enter fullscreen mode Exit fullscreen mode

Detailed Explanation:

  • useState(0) initializes a state variable, count, with a default value of 0. It returns two values:
  • count: The current state value.
  • setCount: A function that updates the state.
  • When you click the button, setCount(count + 1) is called, which updates the count value and triggers a re-render.
  • This is how functional components manage state without needing class components.

2. useEffect Hook

The useEffect hook allows side effects (e.g., data fetching, DOM manipulation, subscriptions) in functional components.

Example:

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

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

  useEffect(() => {
    setTimeout(() => {
      setData('Hello, World!');
    }, 2000);
  }, []);

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

export default DataFetcher;
Enter fullscreen mode Exit fullscreen mode

Detailed Explanation:

  • useEffect runs after every render by default. In this example, it simulates a network request using setTimeout.
  • The effect triggers a side effect to set data (setData('Hello, World!')) after 2 seconds.
  • The empty dependency array [] means this effect will run only once, after the initial render (similar to componentDidMount in class components).
  • If the dependency array contains any state or prop, the effect runs whenever that value changes.

3. useContext Hook

The useContext hook allows functional components to access context data, which avoids prop drilling (passing props down through multiple components).

Example:

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

const ThemeContext = createContext('light');

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

  return <div>The current theme is {theme}</div>;
}

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

export default App;

Enter fullscreen mode Exit fullscreen mode

Detailed Explanation:

  • createContext('light') creates a context with a default value of 'light'.
  • ThemeContext.Provider is a wrapper that provides the value 'dark' to its child components.
  • useContext(ThemeContext) allows DisplayTheme to consume the ThemeContext value ('dark'), without needing to pass it explicitly as a prop.
  • When the value inside ThemeContext.Provider changes, all components consuming this context (DisplayTheme) will automatically update.

4. useReducer Hook

The useReducer hook is a more powerful alternative to useState for managing complex state logic. It is similar to how Redux manages state with actions and reducers.

Example:

import React, { useReducer } from 'react';

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, { count: 0 });

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

export default Counter;
Enter fullscreen mode Exit fullscreen mode

Detailed Explanation:

  • The reducer function takes the current state and an action. Based on the action type, it returns the new state.
  • The useReducer hook returns:
  • state: The current state object ({ count: 0 }).
  • dispatch: A function to send (dispatch) actions.
  • When you click the "+" button, the dispatch({ type: 'increment' }) is called, which triggers the reducer to increment the count.
  • This is especially useful when the state logic is complex or involves multiple sub-values.

5. useMemo Hook

The useMemo hook is used to optimize performance by memoizing (caching) expensive calculations. The calculation will only re-run when dependencies change.

Example:

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

function ExpensiveCalculation() {
  const [number, setNumber] = useState(0);

  const double = useMemo(() => {
    console.log('Calculating...');
    return number * 2;
  }, [number]);

  return (
    <div>
      <p>Number: {number}</p>
      <p>Double: {double}</p>
      <button onClick={() => setNumber(number + 1)}>Increment</button>
    </div>
  );
}

export default ExpensiveCalculation;
Enter fullscreen mode Exit fullscreen mode

Detailed Explanation:

  • useMemo takes two arguments:
  • A function that returns a computed value (in this case, number * 2).
  • An array of dependencies [number]. The computation only runs when number changes.

- This prevents recalculating double on every render if the value of number hasn’t changed, improving performance in cases where the calculation is expensive.

6. useCallback Hook

The useCallback hook is used to memoize (cache) functions. It ensures that the function reference remains the same between renders unless its dependencies change.

Example:

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

function Button({ handleClick }) {
  return <button onClick={handleClick}>Click me</button>;
}

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

  const handleClick = useCallback(() => {
    setCount((prev) => prev + 1);
  }, []); 

  return (
    <div>
      <p>Count: {count}</p>
      <Button handleClick={handleClick} />
    </div>
  );
}

export default Parent;
Enter fullscreen mode Exit fullscreen mode

Detailed Explanation:

  • useCallback(() => { setCount((prev) => prev + 1); }, []) creates a memoized version of the handleClick function.
  • The empty array [] means handleClick will always be the same between renders, unless the component’s state or props change.
  • Without useCallback, the handleClick function would be redefined on every render, causing unnecessary re-renders of the Button component.
  • useCallback is useful when you want to pass stable function references to child components.

7. useRef Hook

The useRef hook is mainly used to directly access DOM elements or persist values across renders without causing a re-render.

Example:

import React, { useRef } from 'react';

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

  const handleClick = () => {
    inputRef.current.focus(); // Access the DOM element directly
  };

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

export default FocusInput;

Enter fullscreen mode Exit fullscreen mode

Detailed Explanation:

  • useRef returns a mutable object { current: null }. This object persists between renders.
  • inputRef.current is the DOM node (input element). You can directly interact with this node, like focusing it when the button is clicked.
  • The difference between useState and useRef is that updating a useRef value does not cause the component to re-render, which is useful when you want to store a value that doesn’t affect the UI.

_In conclusion, these hooks make React functional components powerful by handling state, side effects, memoization, and DOM manipulation, all in a clean and efficient way. They remove the need for class components while keeping the code more concise and easier to manage.
_

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .