DEV Community

Yeshwanth Yadav Kondra
Yeshwanth Yadav Kondra

Posted on • Updated on

Optimizing React Components: When to Use and Not Use useEffect

Maximizing React Performance: Avoiding Unnecessary useEffect Rerenders

useEffect is a hook in React that allows you to perform side effects in your components. A side effect is anything that affects something outside the scope of the current function, such as updating the DOM, fetching data from an API, or subscribing to events. With useEffect, you can manage these side effects in a declarative and predictable way.

Two cases where you can skip using Effects in React:

  1. When you want to modify data before displaying it in your React component, it's better to do it directly in the component instead of using Effects. If you modify the data in an Effect, it could cause your component to re-render multiple times, which is inefficient. Instead, modify the data at the top level of your component, where it will automatically update whenever your props or state change. This will make your code run faster and smoother.

For Example

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

function ItemList({ items }) {
  const [filteredItems, setFilteredItems] = useState(items);

  useEffect(() => {
    const filtered = items.filter(item => item.price < 10);
    setFilteredItems(filtered);
  }, [items]);

  return (
    <ul>
      {filteredItems.map(item => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
}
Enter fullscreen mode Exit fullscreen mode

In this example, we use an Effect to filter the list of items whenever the items prop changes. However, this can cause the component to re-render multiple times unnecessarily. Instead, we can simplify this code by doing the filtering directly in the component:

import React from 'react';

function ItemList({ items }) {
  const filteredItems = items.filter(item => item.price < 10);

  return (
    <ul>
      {filteredItems.map(item => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
}
Enter fullscreen mode Exit fullscreen mode

This code is simpler and more efficient. We filter the list of items directly in the component and store the filtered items in a variable. This code will automatically re-run whenever the items prop changes, so we don't need to use an Effect.

2.You can handle user events like button clicks without using Effects.

For instance, consider the example of a simple form that collects user information and submits it to an API when the user clicks the Submit button. You can handle the form submission in the submit event handler function and update the component state accordingly. You don't need an Effect in this case.

Here's is an example, what I am talking about :

import React, { useState } from 'react';

function UserForm() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');

  function handleSubmit(event) {
    event.preventDefault();
    fetch('/api/user', {
      method: 'POST',
      body: JSON.stringify({ name, email }),
    })
      .then(response => response.json())
      .then(data => {
        alert(`User created with ID ${data.id}`);
        setName('');
        setEmail('');
      });
  }

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Name:
        <input type="text" value={name} onChange={event => setName(event.target.value)} />
      </label>
      <label>
        Email:
        <input type="email" value={email} onChange={event => setEmail(event.target.value)} />
      </label>
      <button type="submit">Submit</button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

Improving Performance by Resetting State on Key Change in React Components

In simpler terms, suppose you have a profile page where users can post comments. You notice that when you switch between profiles, the comment field still holds the previous user's comment, which is not desirable. To fix this, you might be tempted to use an Effect to reset the comment field whenever the user changes. However, this approach is inefficient and can lead to complications if you have nested components with their own state.

Instead, you can use a unique identifier (like the user's ID) as a key when rendering the Profile component. This tells React that each profile is distinct and should have its own state. When the key changes (i.e., when you switch to a different user's profile), React will reset the state of the Profile component and its children automatically. This way, you don't need to use an Effect to reset the comment field.

For example, if you have a list of posts and each post has its own comments section, you can use the post ID as the key for the comments component. This ensures that each comments section has its own state and doesn't interfere with other sections when you switch between posts.

It's important to note that only the outer component (in this case, ProfilePage) needs to pass the key prop to its children. Components that render ProfilePage don't need to worry about this detail.

With useEffect

function ParentComponent(props) {
  useEffect(() => {
    // reset state on prop change
    setState('');
  }, [props.id]);

  return (
    <ChildComponent id={props.id} />
  );
}

function ChildComponent(props) {
  const [state, setState] = useState('');

  return (
    <div>
      <p>Component ID: {props.id}</p>
      <input type="text" value={state} onChange={(e) => setState(e.target.value)} />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Without useEffect

function ParentComponent(props) {
  return (
    <ChildComponent key={props.id} />
  );
}

function ChildComponent(props) {
  const [state, setState] = useState('');

  return (
    <div>
      <p>Component ID: {props.id}</p>
      <input type="text" value={state} onChange={(e) => setState(e.target.value)} />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Here you can find more about when and when not to useEffect in your code. Click here

Thank you !!!

Top comments (0)