What is useEffect Hook in React?

This article provides a clear and concise guide to understanding the useEffect Hook in React. You will learn what useEffect is, why it is used to manage side effects, how to control its execution using the dependency array, and how to perform cleanup operations to prevent memory leaks.

Understanding Side Effects

In React, the primary job of a component is to render the user interface based on state and props. However, components often need to perform actions that reach outside the React rendering cycle. These actions are called side effects.

Common examples of side effects include: * Fetching data from an API. * Manually changing the DOM (e.g., updating the document title). * Setting up subscriptions or WebSockets. * Establishing timers like setTimeout or setInterval.

The useEffect Hook serves as the designated place to handle these side effects in functional components.

Basic Syntax

The useEffect Hook accepts two arguments: a callback function containing the side effect logic, and an optional dependency array.

import { useEffect } from 'react';

useEffect(() => {
  // Side effect logic goes here
}, [dependencies]);

Controlling when useEffect Runs

The behavior of useEffect is determined by its second argument, the dependency array. There are three primary ways to configure it:

1. No Dependency Array

If you omit the dependency array entirely, the hook runs after the initial render and after every subsequent re-render of the component.

useEffect(() => {
  console.log('This runs on every single render');
});

2. Empty Dependency Array []

If you pass an empty array, the hook runs only once after the initial render. This is ideal for one-time setup tasks, such as initial data fetching, similar to componentDidMount in class components.

useEffect(() => {
  console.log('This runs only once after the initial render');
}, []);

3. Dependency Array with Values [prop, state]

If you include specific variables in the array, the hook runs after the initial render and then only when those specified variables change between renders.

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

useEffect(() => {
  console.log(`The count is now ${count}`);
}, [count]); // Runs only when 'count' changes

Cleaning Up Side Effects

Some side effects require cleanup to avoid memory leaks or unexpected behavior, such as clearing intervals or unsubscribing from event listeners.

To perform a cleanup, return a function from your useEffect callback. React will execute this cleanup function before the component unmounts and before running the effect again on subsequent renders.

useEffect(() => {
  const handleResize = () => console.log(window.innerWidth);
  window.addEventListener('resize', handleResize);

  // Cleanup function
  return () => {
    window.removeEventListener('resize', handleResize);
  };
}, []);