Wednesday, 4 December 2024

How to manage Side Effects easily using React useEffect hook?

In React, not all tasks can be achieved through rendering components alone. Some actions, like fetching data, interacting with browser APIs, or setting up subscriptions, need to happen outside the rendering process. These are called side effects and React provides the useEffect hook to manage them seamlessly in functional components. In this article, we'll explore how the useEffect hook works, why it's essential for handling side effects, and how to use it effectively in your React projects.

Syntax of useEffect

useEffect(() => {
  // Effect logic goes here (side effects like API calls, subscriptions, etc.)

  return () => {
    // Optional cleanup logic
  };
}, [dependencies]);

 

The useEffect hook in React is called under several circumstances, depending on how you configure it.

 

1. On Initial Render (Component Mounting)

When the component first renders (mounts), the useEffect hook is triggered.

useEffect(() => {
  // Code runs once when the component mounts
  console.log("Component mounted!");
}, []);  // The empty dependency array makes it run only once.

 

2. On Every Render (Component Updating)

If you omit the second argument (dependency array), the useEffect hook will run after every render (both on mount and after every update).

 

useEffect(() => {
  // Code runs after every render (initial and updates)
  console.log("Component rendered or updated!");
});

 

3. On Specific State/Props Changes

You can pass an array of specific values (state or props) as dependencies. The useEffect will run only when one of these dependencies changes.

 

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

useEffect(() => {
  // Code runs only when 'count' changes
  console.log(`Count value is: ${count}`);
}, [count]);  // Effect depends on 'count' variable

When you pass a dependency array to useEffect, React compares the current values of the dependencies with the previous ones from the last render. This comparison allows React to decide whether the useEffect should be re-run.

 

Internally, React stores (or "caches") the previous values of the dependencies in a special way. On each render, React compares the new values of the dependencies with the cached values from the previous render:

 

1.   If all the dependencies are the same as in the previous render, the effect will not run.

2.   If any dependency has changed compared to the cached values, React will re-run the effect.

 

Example

useEffect(() => {
  console.log("Effect ran");
}, [propA, propB]);

1.   On the first render, React caches the values of propA and propB.

2.   On the next render, React compares the new propA and propB with their cached values.

o   If propA or propB has changed, React will run the effect again and update the cached values.

o   If neither has changed, React will skip running the effect.

 

4. On Component Unmounting (Cleanup)

If your useEffect returns a function, React will call that function when the component unmounts or before the effect runs again (if it's being re-executed due to a dependency change). This is useful for cleanup tasks, such as removing event listeners or canceling API calls.

useEffect(() => {
  const timer = setTimeout(() => {
    console.log("Timer finished!");
  }, 1000);

  return () => {
    // Cleanup the timer when the component unmounts or before the effect reruns
    clearTimeout(timer);
  };
}, []);  // The empty array ensures this cleanup runs only on unmount.

Let’s build an Application to understand the useEffect hook better.

 

Step 1: Go to the post (Quickly Set Up a React Project with Vite: A Step-by-Step), and set up a React Project ‘use-effect-demo’.

 

Project structure looks like below.


 


Step 2: Create components folder in src folder and define UsersInfo component.

 

UsersInfo.jsx

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

export default function UsersInfo() {
  const [users, setUsers] = useState([]);  // State to hold the users

  useEffect(() => {
    // This effect will run when the component is first rendered

    // Fetching data from an API
    fetch('https://jsonplaceholder.typicode.com/users')
      .then(response => response.json())
      .then(data => setUsers(data))  // Update the state with the fetched data
      .catch(error => console.error('Error fetching users:', error));

  }, []);  // The empty dependency array means this runs only on the first render (once)

  return (
    <div>
      <h1>User List</h1>
      <ul>
        {users.map(user => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </div>
  );
}

Step 3: Update main.jsx file like below.

 

main.jsx

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import UsersInfo from './components/UsersInfo'

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <UsersInfo />
  </StrictMode>,
)

Step 4: Build and run the application by executing below commands.

  cd use-effect-demo
  npm install
  npm run dev

Open the url ‘http://localhost:5173/ in browser, you will see below screen.


 

You can download this application from this link.


Previous                                                    Next                                                    Home

No comments:

Post a Comment