React JS useEffect Hook


The useEffect hook is a fundamental part of React's Hooks API, introduced in React 16.8. It allows you to perform side effects in functional components. Side effects are operations that interact with the outside world or impact the state of the component in ways other than rendering, such as data fetching, subscriptions, or manual DOM manipulations.

Key Concepts of useEffect

  1. Basic Usage:

    • The useEffect hook takes a function as its first argument. This function runs after the component renders, and it can optionally return a cleanup function to clean up side effects.
    • Syntax:
      useEffect(() => { // Code to run after render return () => { // Cleanup code (optional) }; }, [dependencies]); // Dependencies array
    • Example:
      import React, { useEffect, useState } from 'react'; function Example() { const [count, setCount] = useState(0); useEffect(() => { document.title = `You clicked ${count} times`; // Cleanup function return () => { document.title = 'React App'; }; }, [count]); // Runs every time `count` changes return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}>Click me</button> </div> ); }
  2. Effect Dependencies:

    • The second argument to useEffect is an optional array of dependencies. The effect runs after every render by default, but specifying dependencies controls when the effect should re-run.
    • Dependencies Array:
      • If you provide an empty array [], the effect runs only once after the initial render (similar to componentDidMount in class components).
      • If you provide specific dependencies [dep1, dep2], the effect runs only when those dependencies change.
      • If you omit the array, the effect runs after every render.
    • Example:
      function FetchData() { const [data, setData] = useState(null); useEffect(() => { fetch('https://api.example.com/data') .then(response => response.json()) .then(data => setData(data)); }, []); // Runs only once after initial render return <div>{data ? JSON.stringify(data) : 'Loading...'}</div>; }
  3. Cleanup Function:

    • The cleanup function is returned from the useEffect callback and is executed before the component unmounts or before the effect runs again. This is useful for cleaning up subscriptions, timers, or other side effects.
    • Example:
      function Timer() { useEffect(() => { const timerId = setInterval(() => { console.log('Timer tick'); }, 1000); // Cleanup function return () => { clearInterval(timerId); }; }, []); // Runs only once after initial render return <div>Check the console for timer output</div>; }
  4. Multiple Effects:

    • You can use multiple useEffect hooks in a single component to handle different side effects separately. This helps keep effects focused and avoids combining unrelated logic.
    • Example:
      function App() { const [count, setCount] = useState(0); const [data, setData] = useState(null); useEffect(() => { document.title = `Count: ${count}`; }, [count]); useEffect(() => { fetch('https://api.example.com/data') .then(response => response.json()) .then(data => setData(data)); }, []); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> <div>Data: {data ? JSON.stringify(data) : 'Loading...'}</div> </div> ); }
  5. Effect Order:

    • Effects are executed after the DOM is updated, so any side effects that affect the DOM should be handled in useEffect to avoid layout thrashing or inconsistent rendering.
    • Effects run in the order they are defined in the component, but the cleanup function for the previous effect will run before the next effect is executed.

Summary

  • useEffect: Allows you to perform side effects in functional components. It accepts a function that runs after every render and can return a cleanup function.
  • Dependencies Array: Controls when the effect should re-run. An empty array means the effect runs once after the initial render. If you specify dependencies, the effect runs when those dependencies change.
  • Cleanup Function: Used to clean up side effects, like clearing timers or unsubscribing from services.
  • Multiple Effects: Use multiple useEffect hooks to handle different side effects separately.
  • Effect Order: Effects run after the DOM is updated, and the cleanup function runs before the effect re-runs or the component unmounts.

The useEffect hook helps manage side effects in a declarative manner, making it easier to handle asynchronous operations, subscriptions, and other side effects in functional components.