Monday, May 25, 2026

Understanding the React ESLint Warning: “Avoid Calling setState() Directly Within an Effect”

While working with React, I encountered an interesting ESLint warning related to useEffect.

The application itself was running perfectly fine, but ESLint still flagged the code with an error.

At first glance, the warning looked confusing because useEffect is supposed to handle side effects like fetching data.

This article explains:

  • what the warning actually means,
  • why ESLint complained,
  • why the corrected version passed,
  • and the deeper React concepts involved.

The Original Code


// Helper function to fetch messages from the backend API
const fetchEntries = async () => {
  try {
    const res = await fetch(API_URL);

    if (!res.ok) {
      throw new Error('Backend failed to respond');
    }

    const data = await res.json();

    setEntries(data);
    setError(null);

  } catch (err) {
    setError('Could not fetch guestbook entries. Is the backend running?');
    console.error(err);
  }
};

// Fetch entries automatically when the page loads
useEffect(() => {
  fetchEntries();
}, []);

  

The ESLint Error

ESLint produced the following warning:

Error: Calling setState synchronously within an effect can trigger cascading renders

Avoid calling setState() directly within an effect

This warning came from:

react-hooks/set-state-in-effect

The Corrected Version

The corrected version moved the async function inside the effect.


useEffect(() => {

  const fetchEntries = async () => {
    try {
      const res = await fetch(API_URL);

      if (!res.ok) {
        throw new Error('Backend failed to respond');
      }

      const data = await res.json();

      setEntries(data);
      setError(null);

    } catch (err) {
      setError('Could not fetch guestbook entries. Is the backend running?');
      console.error(err);
    }
  };

  fetchEntries();

}, []);

  

Interestingly, this version passed ESLint successfully.

Was the Original Code Actually Wrong?

Not really.

Both versions are almost identical in runtime behavior.

The application worked because the state update was not actually synchronous.

The important line is:

await fetch(API_URL);

That await creates an asynchronous boundary.

So the sequence is actually:

useEffect runs

fetch request starts

effect completes

network response arrives later

setState executes

This is very different from:


useEffect(() => {
  setCount(count + 1);
}, []);

  

where the state update happens immediately during the effect execution.

Then Why Did ESLint Complain?

The answer lies in static analysis.

ESLint does not execute the program like a browser does. Instead, it analyzes the source code structure and tries to detect potentially dangerous patterns.

In the original code, ESLint saw:


useEffect(() => {
  fetchEntries();
}, []);

  

and noticed that:

fetchEntries()

contains:

  • setEntries(...)
  • setError(...)

From ESLint’s perspective:

Effect → function call → setState

So it assumed:

“This effect may be synchronously updating state.”

The linter could not safely prove that the state updates only happen after an asynchronous operation.


The complete error as received was: 

error  Error: Calling setState synchronously within an effect can trigger cascading renders


Effects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:

* Update external systems with the latest state from React.

* Subscribe for updates from some external system, calling setState in a callback function when external state changes.


Calling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect).

No comments:

Post a Comment

Understanding the React ESLint Warning: “Avoid Calling setState() Directly Within an Effect”

While working with React, I encountered an interesting ESLint warning related to useEffect . The application itself w...