useEffect Hook

The useEffect hook in React allows you to perform side effects in function components. It is the combination of componentDidMount, componentDidUpdate, and componentWillUnmount lifecycle methods from class components. Side effects can include data fetching, subscriptions, or manually changing the DOM.

Basic Usage

The useEffect hook takes a function as its first argument and an optional dependency array as its second argument.


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

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

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  }, [count]); // Only re-run the effect if count changes

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}

Dependencies

The dependency array tells React when to re-run the effect. If it’s empty ([]), the effect runs only once after the initial render.


useEffect(() => {
  // Effect logic here
}, []); // This effect runs only once

Data Fetching

You can use useEffect to fetch data from an API when the component mounts.


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

export default function DataFetchingComponent() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

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

  if (loading) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      <h1>Data:</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}

Effect Dependencies

The dependency array is crucial for optimizing performance and avoiding unnecessary effect runs. If any value in the dependency array changes, the effect will run again.


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

export default function DependencyComponent({ userId }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    fetch(`https://api.example.com/users/${userId}`)
      .then((response) => response.json())
      .then((data) => setUser(data));
  }, [userId]); // Effect re-runs whenever userId changes

  if (!user) {
     return <div>Loading...</div>;
  }

  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
    </div>
  );
}