10 Must-Know React.js Hooks for Modern Web Development

10 Must-Know React.js Hooks for Modern Web Development

React.js hooks have transformed the way developers build modern web applications. Before React 16.8, managing state and side effects required class components, making the code more complex and harder to maintain. Hooks introduced a cleaner, more functional approach, allowing developers to use state and other React features without writing a class.

Introduction

React.js hooks have transformed the way developers build modern web applications. Before React 16.8, managing state and side effects required class components, making the code more complex and harder to maintain. Hooks introduced a cleaner, more functional approach, allowing developers to use state and other React features without writing a class. In this article, we'll explore 10 essential React.js hooks that every modern developer should know. These hooks help manage state, optimize performance, and enhance code reusability, making them indispensable for React development.

1. useState: Managing Component State

The useState hook is one of the most fundamental hooks in React. It allows functional components to manage local state, eliminating the need for class-based state management.

Syntax and Usage Example

import React, { useState } from 'react';


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


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


Best Practices

  • Always initialize state with a default value.
  • Use functional updates when the new state depends on the previous state.
  • Keep state updates minimal to avoid unnecessary re-renders.

2. useEffect: Handling Side Effects

The useEffect hook allows developers to handle side effects like API calls, event listeners, and subscriptions inside functional components.

Basic Example

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


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


  useEffect(() => {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => setData(data));
  }, []); // Empty dependency array means it runs only once


  return <div>{JSON.stringify(data)}</div>;
}


Best Practices

  • Always clean up subscriptions in the cleanup function.
  • Use dependency arrays carefully to avoid infinite loops.
  • Consider using useCallback to prevent unnecessary re-execution.

3. useContext: Simplifying State Management

The useContext hook simplifies state management by allowing components to access shared state without prop drilling.

Example Usage

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


const ThemeContext = createContext();


function ThemedComponent() {
  const theme = useContext(ThemeContext);
  return <div style={{ background: theme }}>Current Theme: {theme}</div>;
}


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


Why useContext is Useful

  • Reduces prop drilling, making code cleaner.
  • Works well with global state management.
  • Improves maintainability in larger applications.

4. useRef: Accessing DOM Elements and Preserving Values

The useRef hook is commonly used for direct DOM manipulation and storing values between renders without triggering re-renders.

Example: Managing Focus

import React, { useRef } from 'react';


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


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


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


Best Practices

  • Use useRef only when necessary to avoid bypassing React's state management.
  • Great for persisting values like timers and previous state references.

5. useReducer: Advanced State Management

The useReducer hook is useful for managing complex state logic, offering a more structured approach than useState.

Basic 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>
  );
}


When to Use useReducer

  • When state logic is complex or involves multiple sub-values.
  • When state transitions depend on previous state values.

6. useMemo: Performance Optimization with Memoization

The useMemo hook helps optimize performance by memoizing expensive computations, preventing unnecessary recalculations during renders.

Example: Optimizing Expensive Calculations

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


function ExpensiveComponent({ num }) {
  const calculateFactorial = (n) => {
    console.log('Calculating...');
    return n <= 1 ? 1 : n * calculateFactorial(n - 1);
  };


  const memoizedValue = useMemo(() => calculateFactorial(num), [num]);


  return <p>Factorial of {num}: {memoizedValue}</p>;
}


export default function App() {
  const [count, setCount] = useState(5);
  return (
    <div>
      <ExpensiveComponent num={count} />
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}


Best Practices

  • Use useMemo only when performance issues arise.
  • Avoid overusing it, as premature optimization can lead to unnecessary complexity.
  • Ensure dependencies are correctly managed in the dependency array.

7. useCallback: Preventing Unnecessary Function Re-Creation

The useCallback hook prevents unnecessary function re-creations by memoizing callback functions, improving performance in components with frequent re-renders.

Example: Memoizing Event Handlers

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


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


export default function App() {
  const [count, setCount] = useState(0);


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


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


8. useLayoutEffect: Running Effects Before Painting

useLayoutEffect is similar to useEffect, but it runs synchronously after all DOM mutations and before the browser paints.

Example: Measuring DOM Elements Before Painting

import React, { useState, useRef, useLayoutEffect } from 'react';


function MeasureComponent() {
  const divRef = useRef(null);
  const [height, setHeight] = useState(0);


  useLayoutEffect(() => {
    setHeight(divRef.current.getBoundingClientRect().height);
  }, []);


  return (
    <div>
      <div ref={divRef} style={{ padding: '20px', background: 'lightblue' }}>
        Resize me
      </div>
      <p>Height: {height}px</p>
    </div>
  );
}


When to Use useLayoutEffect

  • When you need to measure or manipulate the DOM before it’s displayed.
  • When dealing with animations or layout shifts.
  • Avoid using it unless necessary, as it can block rendering.

9. useImperativeHandle: Customizing Ref Exposures in Components

useImperativeHandle allows customization of a component’s exposed methods when using forwardRef.

Example: Exposing a Custom Method

import React, { useRef, useImperativeHandle, forwardRef } from 'react';


const CustomInput = forwardRef((props, ref) => {
  const inputRef = useRef();


  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    },
  }));


  return <input ref={inputRef} type="text" />;
});


export default function App() {
  const inputRef = useRef();


  return (
    <div>
      <CustomInput ref={inputRef} />
      <button onClick={() => inputRef.current.focus()}>Focus Input</button>
    </div>
  );
}


When to Use useImperativeHandle

  • When you need to expose specific functionalities of a component.
  • When dealing with uncontrolled components like form inputs or modals.
  • Use sparingly, as it breaks encapsulation principles.

10. Custom Hooks: Creating Reusable Logic

Custom hooks allow developers to extract and reuse logic across multiple components, promoting cleaner and more maintainable code.

Example: Creating a useFetch Hook

import { useState, useEffect } from 'react';


function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);


  useEffect(() => {
    fetch(url)
      .then((res) => res.json())
      .then((data) => {
        setData(data);
        setLoading(false);
      })
      .catch((err) => {
        setError(err);
        setLoading(false);
      });
  }, [url]);


  return { data, loading, error };
}


export default useFetch;


Example Usage in a Component

import React from 'react';
import useFetch from './useFetch';


function UsersList() {
  const { data, loading, error } = useFetch('https://jsonplaceholder.typicode.com/users');


  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;


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


export default UsersList;


Why Use Custom Hooks?

  • Promotes code reuse and better organization.
  • Keeps components clean and focused on UI logic.
  • Encourages the separation of concerns.

Conclusion

React hooks have drastically simplified the way developers build modern applications. From basic state management with useState to performance optimization with useMemo and useCallback, hooks offer powerful tools to make React development more efficient. Mastering these 10 essential hooks will help you write cleaner, more maintainable, and optimized React applications. Experiment with them, and start integrating them into your projects for better performance and reusability.

0
147
Hyperparameter Tuning: How to Improve Machine Learning Model Performance

Hyperparameter Tuning: How to Improve Machine Learning Model Performan...

defaultuser.png
CodeWithDiv
1 month ago
SEO for Web Developers: How to Optimize Your Website for Search Engines in 2025

SEO for Web Developers: How to Optimize Your Website for Search Engine...

defaultuser.png
CodeWithDiv
1 month ago
Top DevOps Tools in 2025: A Comprehensive Guide

Top DevOps Tools in 2025: A Comprehensive Guide

defaultuser.png
CodeWithDiv
1 month ago
Edge Computing vs. Cloud Computing: What’s the Difference and Why It Matters

Edge Computing vs. Cloud Computing: What’s the Difference and Why It M...

defaultuser.png
CodeWithDiv
1 month ago
React vs Vue vs Angular: Which Framework Should You Choose in 2025?

React vs Vue vs Angular: Which Framework Should You Choose in 2025?

defaultuser.png
CodeWithDiv
1 month ago