React Cannot update a component while rendering a different component

Debugging React applications has been a big part of my daily work for more than a decade. Over the years, I’ve seen many errors, but one that often confuses developers is:

“Warning: Cannot update a component while rendering a different component.”

When I first came across this, I was working on a dashboard for a U.S. retail client. The app had multiple forms, charts, and authentication flows. Suddenly, this warning popped up, and my console was flooded with yellow messages.

In this tutorial, I’ll walk you through why this happens and, more importantly, how to fix it. I’ll share multiple methods along with full working code examples. Each method has a short explanation below it, so you can apply the fix immediately.

What Does This Warning Mean?

This warning appears when you try to update a state in one component while React is still rendering another component.

React’s rendering process is strict. It doesn’t allow you to modify state or trigger updates in the middle of rendering another component. Doing so can cause inconsistent UI and broken renders.

For example:

  • Updating the parent state directly while rendering a child.
  • Triggering setState inside the render body.
  • Calling navigation or context updates during render.

Method 1: Move State Updates to useEffect

One of the most common causes is calling setState directly during rendering. Instead, you should move the update into a useEffect hook.

Example

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

function Register({ onRegister }) {
  const [registered, setRegistered] = useState(false);

  //  Wrong: This would cause the warning if placed inside render
  // if (!registered) {
  //   setRegistered(true);
  //   onRegister();
  // }

  //  Correct: Move state update into useEffect
  useEffect(() => {
    if (!registered) {
      setRegistered(true);
      onRegister();
    }
  }, [registered, onRegister]);

  return <div>Registering user...</div>;
}

function App() {
  const [status, setStatus] = useState("Not Registered");

  const handleRegister = () => {
    setStatus("Registered Successfully");
  };

  return (
    <div>
      <h1>{status}</h1>
      <Register onRegister={handleRegister} />
    </div>
  );
}

export default App;

I executed the above example code and added the screenshot below.

React Cannot update a component while rendering a different component

Here, instead of calling setRegistered inside the render body, I moved it into a useEffect. This ensures the update only happens after the render cycle completes.

Method 2: Use a Callback Instead of Direct State Updates

Sometimes, the issue comes from updating the parent state directly from a child during render. The fix is to use a callback function passed as a prop.

Example

import React, { useState } from "react";

function Child({ notifyParent }) {
  //  Wrong: Directly updating parent during render would cause the warning
  // notifyParent("Child is ready");

  //  Correct: Trigger parent update on an event (like button click)
  return (
    <button onClick={() => notifyParent("Child is ready")}>
      Notify Parent
    </button>
  );
}

function App() {
  const [message, setMessage] = useState("Waiting...");

  return (
    <div>
      <h2>{message}</h2>
      <Child notifyParent={setMessage} />
    </div>
  );
}

export default App;

I executed the above example code and added the screenshot below.

React Cannot update a component while rendering a different component Warning

Instead of calling setMessage during render, I only call it when the button is clicked. This avoids the warning and keeps the app predictable.

Method 3: Use Context the Right Way

If you’re using React Context, you might accidentally update context inside render. The fix is to update context values inside an event or effect.

Example

import React, { useState, useContext, createContext, useEffect } from "react";

const AuthContext = createContext();

function AuthProvider({ children }) {
  const [user, setUser] = useState(null);

  const login = (name) => {
    setUser({ name });
  };

  return (
    <AuthContext.Provider value={{ user, login }}>
      {children}
    </AuthContext.Provider>
  );
}

function LoginForm() {
  const { user, login } = useContext(AuthContext);

  useEffect(() => {
    if (!user) {
      login("John Doe"); //  Safe inside useEffect
    }
  }, [user, login]);

  return <div>{user ? `Welcome ${user.name}` : "Logging in..."}</div>;
}

function App() {
  return (
    <AuthProvider>
      <LoginForm />
    </AuthProvider>
  );
}

export default App;

I executed the above example code and added the screenshot below.

Cannot update a component while rendering a different component React

Here, I call the login inside useEffect instead of directly in the render body. This ensures the context update happens after rendering.

Method 4: Avoid Conditional State Updates in Render

Another common mistake is conditionally setting state during render. The correct approach is to compute values or use useMemo.

Example

import React, { useState, useMemo } from "react";

function ScoreBoard({ scores }) {
  const [highlight, setHighlight] = useState(null);

  //  Wrong: Directly setting state during render
  // if (scores.length > 5) {
  //   setHighlight("High Activity");
  // }

  //  Correct: Use useMemo to compute derived state
  const highlightText = useMemo(() => {
    return scores.length > 5 ? "High Activity" : "Normal";
  }, [scores]);

  return (
    <div>
      <h3>Scores: {scores.join(", ")}</h3>
      <p>Status: {highlightText}</p>
    </div>
  );
}

function App() {
  return <ScoreBoard scores={[10, 20, 30, 40, 50, 60]} />;
}

export default App;

Instead of calling setHighlight during render, I used useMemo to calculate the derived value. This avoids unnecessary state updates.

Method 5: Use useLayoutEffect for Immediate Updates

In rare cases, you may need to update the state immediately after DOM mutations. Instead of doing it in render, use useLayoutEffect.

Example

import React, { useState, useLayoutEffect, useRef } from "react";

function AutoFocusInput() {
  const [focused, setFocused] = useState(false);
  const inputRef = useRef();

  useLayoutEffect(() => {
    if (!focused) {
      inputRef.current.focus();
      setFocused(true);
    }
  }, [focused]);

  return <input ref={inputRef} placeholder="Type here..." />;
}

function App() {
  return (
    <div>
      <h2>Auto Focus Example</h2>
      <AutoFocusInput />
    </div>
  );
}

export default App;

Here, I used useLayoutEffect to focus the input right after render. This ensures the DOM is updated before React paints the screen.

  • Never call setState inside the render body.
  • Use useEffect or useLayoutEffect for updates after render.
  • Pass callbacks to children instead of updating parent state directly.
  • Use useMemo for derived values instead of conditional state updates.
  • Keep context updates outside of render logic.

I’ve personally run into this React warning many times, especially while building large-scale apps for U.S. clients in finance and retail. The fix always comes down to the same principle:

Don’t trigger updates during render.

If you follow the methods I’ve shared, moving updates into useEffect, using callbacks, handling context properly, and avoiding conditional state updates, you’ll never see this warning again.

You may also read:

Leave a Comment

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.