Home   reactjs  

does useEffect get called on every render?

The useEffect hook in React is designed to run side effects in function components. By default, useEffect runs after the first render and after every update. The reason it runs initially, even though you haven't clicked the button or changed the count, is because that's how useEffect is designed to work.

Here's a detailed explanation:

How useEffect Works

  1. Initial Render:
    • useEffect is called after the initial render. This ensures that side effects (like fetching data, subscribing to services, etc.) are run as soon as the component mounts.
  2. Subsequent Renders:
    • If the dependencies array is provided, useEffect runs only when one of the dependencies has changed since the last render.
    • If an empty dependencies array ([]) is provided, useEffect runs only once, after the initial render.

Example Breakdown

Let’s modify the previous example to include a useEffect hook:

import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';

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

  useEffect(() => {
    console.log('useEffect called');
  }, []); // The empty array ensures this runs only once, after the initial render

  console.log('Rendering App');

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

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

Explanation

  1. Initial Render:

    • console.log('Rendering App') is executed when the component renders.
    • The useEffect hook runs after the initial render, logging useEffect called.
    • The component renders the UI, displaying the count and the button.
  2. Effect Behavior:

    • Because the dependencies array ([]) is empty, useEffect runs only once, after the initial render.
    • Any state changes (like clicking the button to increment the count) will not trigger useEffect again, because the dependencies array is empty and doesn't include count.

Common Patterns with useEffect

  1. Run on Every Render:

    useEffect(() => {
      console.log('useEffect called');
    });
    

    This runs after every render (initial and updates).

  2. Run Once After Initial Render:

    useEffect(() => {
      console.log('useEffect called');
    }, []); // Empty array ensures this runs only once
    
  3. Run When Dependencies Change:

    useEffect(() => {
      console.log('useEffect called because count changed');
    }, [count]); // Runs only when `count` changes
    

Practical Example with Side Effect

Here's a practical example of using useEffect to fetch data when the component mounts:

import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';

const App = () => {
  const [count, setCount] = useState(0);
  const [data, setData] = useState(null);

  useEffect(() => {
    console.log('Fetching data...');
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => setData(data));
  }, []); // Fetch data only once when component mounts

  console.log('Rendering App');

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <div>{data ? JSON.stringify(data) : 'Loading data...'}</div>
    </div>
  );
};

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

In this example, useEffect is used to fetch data from an API when the component mounts. The fetch call runs only once due to the empty dependencies array.

Published on: Jul 05, 2024, 05:43 AM  
 

Comments

Add your comment