Lecture Notes Of Day 12: The useEffect Hook

Rashmi Mishra
0

 

Lecture Notes Of Day 12: The useEffect Hook

Objective:

Deep dive into the useEffect hook and its uses in React applications.

Outcome:

Learn how to manage side effects like API calls, DOM updates, or event listeners using the useEffect hook. By the end of the class, you will understand how and when to use useEffect in functional components to handle side effects.


1. What is useEffect?

In React, the useEffect hook is used to manage side effects in functional components. Side effects refer to operations that can interact with the outside world, such as:

  • Making API calls to fetch data
  • Updating the DOM (not related to the render output)
  • Setting up or cleaning up subscriptions, timers, or event listeners

Before React hooks, managing side effects was only possible in class components via lifecycle methods like componentDidMount, componentDidUpdate, and componentWillUnmount. useEffect consolidates all these into a single hook that can be used in functional components.

2. Syntax of useEffect

The basic syntax of useEffect is:

javascript

Copy code

useEffect(() => {

  // side effect logic here

}, [dependencies]);

  • First Argument (callback function): This is the function that contains the code to perform the side effect. This function runs after the component renders. The effect can also return a cleanup function (to clean up resources when the component unmounts or when dependencies change).
  • Second Argument (dependency array): This is an optional array of dependencies that tells React when to re-run the effect. If you pass an empty array [], the effect will only run once after the initial render. If you don't pass the second argument, the effect will run after every render.

3. How useEffect Works

  • The effect function runs after the render and not during the render process, which ensures that it doesn’t block the rendering of the UI.
  • By default, useEffect will run after every render. However, you can control when it runs using the dependency array.

4. Example: Basic Usage of useEffect

Let's see a simple example of how useEffect is used in a functional component.

javascript

Copy code

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

 

function App() {

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

 

  // This useEffect runs after every render

  useEffect(() => {

    console.log('Component rendered or count changed:', count);

  });

 

  return (

    <div>

      <p>Count: {count}</p>

      <button onClick={() => setCount(count + 1)}>Increment</button>

    </div>

  );

}

 

export default App;

Explanation:

  • The useEffect hook here logs a message to the console every time the component is rendered or when the count state changes.
  • This happens after the component renders and not during the render.

5. Using useEffect for API Calls

A very common use of useEffect is to fetch data from an API after a component renders.

javascript

Copy code

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

 

function App() {

  const [data, setData] = useState([]);

 

  useEffect(() => {

    // Fetch data from API

    fetch('https://api.example.com/data')

      .then(response => response.json())

      .then(data => setData(data))

      .catch(error => console.error('Error fetching data:', error));

  }, []); // Empty array means it runs once after initial render

 

  return (

    <div>

      <h1>Data:</h1>

      <ul>

        {data.map(item => (

          <li key={item.id}>{item.name}</li>

        ))}

      </ul>

    </div>

  );

}

 

export default App;

Explanation:

  • In this example, useEffect makes an API call when the component mounts (initial render).
  • The empty dependency array [] ensures that the effect only runs once, similar to componentDidMount in class components.

6. Cleanup in useEffect

Sometimes, you need to clean up resources when the component unmounts or when the effect runs again. You can do this by returning a cleanup function from useEffect.

For example, if you set up an event listener or a timer, you might want to remove them when the component is removed or before the effect runs again.

javascript

Copy code

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

 

function Timer() {

  const [time, setTime] = useState(0);

 

  useEffect(() => {

    const timerId = setInterval(() => {

      setTime(prevTime => prevTime + 1);

    }, 1000);

 

    // Cleanup function to clear the timer

    return () => clearInterval(timerId);

  }, []); // Runs only once when the component mounts

 

  return (

    <div>

      <h1>Time: {time}s</h1>

    </div>

  );

}

 

export default Timer;

Explanation:

  • In this example, useEffect sets up a timer that increments the time state every second.
  • The cleanup function (clearInterval(timerId)) is returned from useEffect, ensuring that the interval is cleared when the component unmounts, preventing memory leaks.

7. Dependencies in useEffect

The dependency array allows you to control when the effect should run. If you pass variables inside the array, the effect will only run when one of those variables changes.

javascript

Copy code

useEffect(() => {

  console.log('Count changed:', count);

}, [count]); // Only runs when "count" changes

If you pass an empty array ([]), the effect will run only once after the initial render. If you pass no array at all, the effect will run after every render.

8. Conditional Effect Execution

You can also control when an effect should run by adding conditional logic inside the useEffect callback:

javascript

Copy code

useEffect(() => {

  if (count > 5) {

    console.log('Count is greater than 5');

  }

}, [count]);

9. Best Practices for useEffect

  • Avoid side effects that affect rendering: Keep side effects that modify the UI outside the render logic.
  • Use clean-up functions: Always clean up timers, subscriptions, or event listeners to avoid memory leaks.
  • Keep effects focused: Keep effects small and focused on a single responsibility. If an effect becomes too complex, consider breaking it into multiple useEffect calls.
  • Be mindful of dependencies: Always include all the state and props that the effect depends on in the dependency array.

10. Summary

  • useEffect is a hook for managing side effects in React functional components.
  • It runs after the render and can be used for operations like API calls, DOM manipulation, event listeners, and more.
  • It can run conditionally based on dependencies and can be cleaned up to prevent memory leaks.
  • By controlling the dependencies, you can ensure that the effect runs only when necessary.

Assignment/Practice:

1.  Create a React app that fetches a list of users from a public API and displays them.

2.  Implement a button that changes the background color of the page when clicked. Use useEffect to clean up any side effects.

3.  Set up a timer using useEffect that displays the time since the component was mounted. Ensure that the timer is cleaned up when the component unmounts.


These additional assignments further explore the useEffect hook, covering aspects like cleanup, conditional rendering based on dependency changes, and error handling in API calls. 



Post a Comment

0Comments

Post a Comment (0)