React :👈 👉:Twice execution of useEffect in React

Too Many Re-renders in React

Re-renders in React can significantly impact performance, especially when they occur excessively. Understanding the causes and solutions for too many re-renders is crucial for building efficient React applications.

Too Many Re-renders in React

1. Quick Answer

Too many re-renders in React occurs when a component repeatedly updates its state during rendering, causing React to render the component again and again without reaching a stable state.

React detects this infinite rendering loop and stops it by throwing an error:

Too many re-renders. React limits the number of renders to prevent an infinite loop.

Common cause: Calling a state update function directly inside the component body instead of inside an event handler or an appropriate Effect.

Incorrect example:

function Counter() {
    const [count, setCount] = useState(0);
    setCount(count + 1);
    return <h1>Count: {count}</h1>;
}

Correct example:

function Counter() {
    const [count, setCount] = useState(0);
    return (
        <div>
            <h1>Count: {count}</h1>
            <button onClick={() => setCount(count + 1)}>
                Increment
            </button>
        </div>
    );
}

In the correct example, the state changes only when the user clicks the button, rather than during every render.

2. Table of Contents

  1. Concept Explanation
  2. Diagram
  3. Real-World Example
  4. Code Examples
  5. Common Mistakes
  6. When to Use It
  7. When NOT to Use It
  8. Interview Questions

3. Concept Explanation

3.1 What Is Rendering in React?

Rendering is the process through which React executes a component to determine what the user interface should display.

A React component may render again when:

  • Its state changes.
  • Its parent component renders again.
  • Its context value changes.
  • A subscribed external store reports a relevant update.

Re-rendering is a normal part of React. The problem occurs when rendering repeatedly triggers another state update, creating an endless loop.

3.2 How Does a State Update Work?

Consider the following example:

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

Here:

  • count represents the current state value.
  • setCount is the function used to request a state update.
  • useState(0) initializes the state to zero.

When you call setCount(1), React schedules a state update. React may then render the component again using the updated state.

If the component calls setCount unconditionally during every render, the following sequence occurs:

  1. The component renders.
  2. The component updates its state.
  3. React renders the component again.
  4. The component updates its state again.
  5. The cycle continues until React stops it with an error.

3.3 Why Does React Throw This Error?

React prevents uncontrolled rendering loops because they can consume excessive processing resources and prevent the application from displaying the expected interface.

The error is a safeguard that stops the component from repeatedly rendering because of an unstable state-update pattern.

3.4 Re-rendering vs. Infinite Re-rendering

Aspect Normal Re-rendering Infinite Re-rendering
Cause A state, prop, context, or subscribed store update. A repeated update cycle without reaching a stable state.
Behavior The component updates when necessary. The component continuously triggers additional updates.
Example Updating a counter when a button is clicked. Updating the counter unconditionally inside the component body.
Result The user interface displays the updated state. React eventually throws an error when its render limit is exceeded.

4. Diagram

4.1 Infinite Re-rendering Flow

Component Starts Component Renders State Updated During Render React Renders Again State Updated During Render React Renders Again Infinite Loop React Throws Error

4.2 Correct Rendering Flow

Component Starts Component Renders User Clicks Button Event Handler Executes State Is Updated React Renders Again Updated UI Is Displayed Stable State

Key takeaway: State updates should normally happen in response to events or when a genuine synchronization requirement exists, rather than unconditionally during rendering.

5. Real-World Example

Scenario: Online Shopping Cart

Imagine an online shopping application displaying the number of products in a shopping cart.

The application maintains the following state:

const [cartCount, setCartCount] = useState(0);

The developer wants to increase the cart count when the user clicks the Add to Cart button.

Incorrect Implementation

function ShoppingCart() {
    const [cartCount, setCartCount] = useState(0);
    setCartCount(cartCount + 1);
    return (
        <div>
            <h2>Shopping Cart</h2>
            <p>Items in cart: {cartCount}</p>
        </div>
    );
}

What happens?

  1. The component renders with cartCount = 0.
  2. setCartCount(1) requests a state update.
  3. React renders the component again with cartCount = 1.
  4. setCartCount(2) requests another update.
  5. The process repeats until React throws the too-many-re-renders error.

Correct Implementation

function ShoppingCart() {
    const [cartCount, setCartCount] = useState(0);
    function addToCart() {
        setCartCount(count => count + 1);
    }
    return (
        <div>
            <h2>Shopping Cart</h2>
            <p>Items in cart: {cartCount}</p>
            <button onClick={addToCart}>
                Add to Cart
            </button>
        </div>
    );
}

Why does this work?

  • The initial render displays a cart count of zero.
  • The state does not change automatically during rendering.
  • When the user clicks Add to Cart, the event handler executes.
  • The functional state update calculates the next count using the previous state.
  • React renders the updated cart count.

This approach prevents an infinite rendering loop and matches the intended business behavior.

6. Code Examples

6.1 Mistake: Calling a State Setter During Rendering

import { useState } from "react";
function Example() {
    const [name, setName] = useState("React");
    setName("JavaScript");
    return <h1>{name}</h1>;
}
export default Example;

Problem: Every render requests another state update, even when the component has no reason to change the name.

Solution: Update the state in response to a user action, or use an appropriate Effect if synchronization with an external system is required.

6.2 Mistake: Calling an Event Handler Instead of Passing It

Incorrect code:

function Counter() {
    const [count, setCount] = useState(0);
    function increment() {
        setCount(count + 1);
    }
    return (
        <button onClick={increment()}>
            Increment
        </button>
    );
}

Problem: The expression increment() executes immediately while React is rendering the component. It does not wait for the user to click the button.

If the handler updates state, it can trigger a rendering loop.

Correct code:

function Counter() {
    const [count, setCount] = useState(0);
    function increment() {
        setCount(count + 1);
    }
    return (
        <button onClick={increment}>
            Increment
        </button>
    );
}

Passing increment gives React a function to execute when the click event occurs.

6.3 Using an Arrow Function for Event Handlers

import { useState } from "react";
function Counter() {
    const [count, setCount] = useState(0);
    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={() => setCount(count + 1)}>
                Increment
            </button>
        </div>
    );
}
export default Counter;

The arrow function ensures that the state update happens when the button is clicked, not when the component renders.

6.4 Mistake: Unconditional State Updates Inside useEffect

A rendering loop can also occur when an Effect updates state after every render and that update causes another render.

Incorrect code:

import { useEffect, useState } from "react";
function Example() {
    const [count, setCount] = useState(0);
    useEffect(() => {
        setCount(count + 1);
    });
    return <p>Count: {count}</p>;
}

Problem: Without a dependency array, the Effect runs after every committed render. The state update triggers another render, which causes the Effect to run again.

Correct code when the intention is to initialize a value once:

import { useEffect, useState } from "react";
function Example() {
    const [count, setCount] = useState(0);
    useEffect(() => {
        setCount(1);
    }, []);
    return <p>Count: {count}</p>;
}

The empty dependency array means that this Effect does not re-run simply because the component renders again. In development Strict Mode, React may run an extra Effect setup cycle to help detect bugs, so Effects should still be written carefully.

Important: Do not add an empty dependency array automatically to every Effect. Choose dependencies according to the values and synchronization requirements the Effect actually uses. If the state can be calculated directly during rendering, an Effect may not be necessary at all.

6.5 Mistake: Updating State Based on a Value That Can Be Calculated

Unnecessary implementation:

function PriceCalculator() {
    const [price, setPrice] = useState(100);
    const [quantity, setQuantity] = useState(2);
    const [total, setTotal] = useState(200);
    useEffect(() => {
        setTotal(price * quantity);
    }, [price, quantity]);
    return <p>Total: {total}</p>;
}

This example does not necessarily create an infinite loop because the Effect only depends on price and quantity. However, it introduces unnecessary state and an additional rendering cycle when the total changes.

Simpler implementation:

function PriceCalculator() {
    const [price, setPrice] = useState(100);
    const [quantity, setQuantity] = useState(2);
    const total = price * quantity;
    return (
        <div>
            <p>Price: {price}</p>
            <p>Quantity: {quantity}</p>
            <p>Total: {total}</p>
        </div>
    );
}

Because total is derived from price and quantity, it can be calculated directly during rendering. This avoids keeping redundant state synchronized.

6.6 Mistake: Updating State Based on Previous State Incorrectly

When the next state depends on the previous state, use the functional updater form when appropriate.

Example:

setCount(previousCount => previousCount + 1);

This tells React to calculate the next value from the previous state. It is particularly useful when multiple updates may be queued before React renders again.

However, the functional updater does not itself prevent infinite rendering. Calling it unconditionally during rendering is still incorrect.

6.7 A Special Case: Conditional State Updates During Rendering

React permits a narrow exception: a component can conditionally update its own state during rendering when it needs to adjust state based on information from a previous render. React discards that render and retries the component.

For example:

function List({ items }) {
    const [previousItems, setPreviousItems] = useState(items);
    const [selection, setSelection] = useState(null);
    if (items !== previousItems) {
        setPreviousItems(items);
        setSelection(null);
    }
    return (
        <div>
            <p>Items: {items.length}</p>
            <p>Selected: {selection ?? "None"}</p>
        </div>
    );
}

This pattern is a specialized technique, not the default solution. The condition must ensure that the update stops after React retries the component. In many cases, restructuring the state or using a component key to reset state is simpler.

7. Common Mistakes

Mistake Why It Is a Problem Correct Approach
Calling a state setter directly in the component body Triggers another render on every render. Update state in an event handler or a justified Effect.
Using onClick={handleClick()} Executes the function immediately during rendering. Use onClick={handleClick}.
Using an Effect without dependencies to update state unconditionally The Effect runs after each committed render and can repeatedly trigger another render. Use appropriate dependencies or remove the unnecessary Effect.
Updating state without a stopping condition The update cycle never reaches a stable state. Ensure state updates occur only when required.
Storing calculated values in state unnecessarily Creates redundant state and synchronization overhead. Calculate derived values during rendering.
Assuming useCallback fixes every rendering loop Memoizing a function does not fix an unconditional state update. Correct the underlying state-update logic.
Adding an empty dependency array to every Effect May prevent the intended synchronization when dependencies change. Specify dependencies according to the Effect's actual requirements.
Assuming every re-render is a bug React is designed to render components again when their inputs change. Investigate repeated or unnecessary updates rather than eliminating all re-renders.

How to Debug the Error

  1. Read the component named in the error stack trace.
  2. Search for calls to setState, state setters such as setCount, or other functions that trigger updates.
  3. Check whether those functions execute directly in the component body.
  4. Inspect event handlers for expressions such as onClick={handleClick()}.
  5. Inspect Effects for state updates that cause the same Effect to run repeatedly.
  6. Check whether a dependency changes on every render and repeatedly triggers an Effect.
  7. Move event-driven updates into event handlers and remove unnecessary state synchronization.
  8. Test the component again and verify that it reaches a stable state.

8. When to Use It

The phrase "too many re-renders" describes an error condition, not a React feature that developers should intentionally use.

However, understanding this error is useful in the following situations:

  • Debugging state updates: When a component crashes because React detects repeated rendering.
  • Handling user interactions: When implementing buttons, forms, counters, filters, and shopping carts.
  • Managing derived values: When deciding whether a value should be stored in state or calculated from existing data.
  • Using Effects correctly: When synchronizing a component with external systems, such as browser APIs, subscriptions, or network connections.
  • Reviewing component design: When identifying redundant state updates and unnecessary synchronization.
  • Improving application stability: When preventing rendering loops from interrupting normal user interactions.

Recommended Practices

  • Keep rendering logic pure: rendering should calculate the UI without causing unintended side effects.
  • Use state setters in event handlers for user-triggered updates.
  • Use Effects when synchronization with an external system is genuinely needed.
  • Calculate derived values directly whenever practical.
  • Use functional state updates when the next state depends on the previous state.
  • Make sure conditional state updates have a valid stopping condition.

9. When NOT to Use It

Because this is an error condition, you should not deliberately create an infinite rendering loop in a real application.

Also, do not confuse the error with ordinary re-rendering. Avoid the following incorrect approaches when trying to fix it:

  • Do not remove every state update: State is necessary for interactive components.
  • Do not move every state update into an Effect: User-triggered updates generally belong in event handlers.
  • Do not add arbitrary timeouts: Delaying a repeated update does not fix the underlying logic.
  • Do not use useMemo or useCallback as a universal fix: These Hooks do not prevent unconditional state updates.
  • Do not disable React Strict Mode to hide the problem: Strict Mode helps expose certain bugs during development; it is not the underlying cause of an unconditional render-time state update.
  • Do not use an empty dependency array without considering the Effect's requirements: This can produce stale values or incorrect synchronization.
  • Do not store duplicate state unnecessarily: If a value can be calculated from existing props or state, consider calculating it directly.

Important distinction: React can render a component multiple times without causing this error. The objective is to eliminate the unintended update loop, not to prevent all re-renders.

10. Interview Questions

Q1. What does "Too many re-renders" mean in React?

Answer: It means a component is repeatedly triggering updates during rendering, creating a loop that React cannot stabilize. React stops the process and throws an error to prevent uncontrolled rendering.

Q2. What is the most common cause of this error?

Answer: Calling a state setter unconditionally inside the component body.

setCount(count + 1);

This statement should not execute unconditionally during rendering.

Q3. What is the difference between onClick={handleClick} and onClick={handleClick()}?

Answer:

  • onClick={handleClick} passes the function to React so it can execute when the user clicks.
  • onClick={handleClick()} executes the function immediately while rendering and passes its return value to the event handler property.

If the function updates state, the second form can trigger repeated rendering.

Q4. Can useEffect cause a too-many-re-renders error?

Answer: Yes, a state update inside an Effect can create an infinite update loop when the Effect repeatedly runs and its state update causes the Effect to run again. An Effect without a dependency array that unconditionally updates state is a common example.

Q5. Does every state update cause an infinite rendering loop?

Answer: No. A state update normally requests a new render. An infinite loop occurs when rendering or an Effect repeatedly triggers additional updates without reaching a stable state.

Q6. How do you fix an infinite rendering loop?

Answer: Identify the repeated state update, move event-driven updates into event handlers, correct Effect dependencies when necessary, and remove unnecessary state synchronization.

Q7. Can useCallback solve the too-many-re-renders error?

Answer: Not by itself. useCallback memoizes a function reference between renders when its dependencies remain unchanged. It does not prevent a state setter from executing unconditionally during rendering.

Q8. What is the difference between rendering and committing in React?

Answer: During rendering, React calculates what the UI should look like. During the commit phase, React applies the necessary changes to the DOM. Effects run after a commit according to their scheduling rules.

Q9. Why should derived state often be calculated directly?

Answer: A value derived from existing props or state usually does not need a separate state variable. Calculating it directly avoids redundant state, synchronization problems, and unnecessary additional rendering cycles.

Q10. What is the purpose of React Strict Mode?

Answer: Strict Mode enables additional development-time checks that help identify potential problems in components and Effects. Some functions or Effect setup logic may run an additional time in development. Strict Mode is not the cause of an unconditional state update during rendering, and disabling it is not the correct fix for a rendering loop.

Q11. When should you use a functional state update?

Answer: Use a functional state update when the next state depends on the previous state.

setCount(previousCount => previousCount + 1);

This allows React to calculate the next value from the previous state. It does not, by itself, prevent an infinite loop if the setter is called unconditionally during rendering.

Q12. What is the difference between an unnecessary re-render and an infinite rendering loop?

Answer: An unnecessary re-render occurs when a component renders again without needing to produce a different UI. An infinite rendering loop occurs when repeated state updates continuously trigger additional renders. The former is generally a performance concern; the latter can cause an application error.

Q13. Can changing an Effect dependency cause a rendering loop?

Answer: Yes. If an Effect updates state and a dependency changes as a result, the Effect can run again. A dependency that receives a new object or function reference on every render can also repeatedly trigger an Effect when that reference is included in its dependency list. The solution is to examine the synchronization logic and dependencies rather than blindly removing dependencies.

Q14. What is the best way to prevent too many re-renders?

Answer: Keep component rendering pure, update state in response to appropriate events, use Effects only for genuine synchronization needs, avoid redundant state, and ensure conditional updates eventually stop.

Q15. Explain the error in one sentence.

Answer: React throws the "Too many re-renders" error when a component repeatedly triggers state updates during rendering, preventing React from reaching a stable UI.

Summary

  • Re-rendering is normal in React; an uncontrolled rendering loop is not.
  • Never call a state setter unconditionally inside the component body.
  • Pass event-handler functions instead of executing them during rendering.
  • Check Effects for repeated state updates and incorrect dependencies.
  • Calculate derived values directly when possible.
  • Use functional state updates when the next value depends on the previous state.
  • Fix the underlying update logic rather than trying to suppress the error.
Back to Index
React :👈 👉:Twice execution of useEffect in React