Skip to content

[DevTools Bug]: Internal state change in cousin component causing a "re-render" in another cousin component wrapped inside parent divs. #35245

@mukesharyal

Description

@mukesharyal

Website or app

https://github.com/mukesharyal/react-devtools-bug-report

Repro steps

  1. Clone the GitHub repo and run npm install
  2. Run the local dev server with npm run dev and also run React Devtools
  3. You will see two components ComponentA and ComponentB
  4. Cause a re-render of ComponentA by clicking the button a bunch of times
  5. ComponentB will also be shown in the component render highlights and Profiler sessions

The structure of App component looks like this:

import ComponentA from './components/ComponentA';
import ComponentB from './components/ComponentB';

function App() {

	return(

		<div>
			<div>
				<ComponentA />
			</div>

			

			<div>
				<ComponentB />
			</div>
		</div>
	);

}

export default App;

This is what ComponentA looks like:

import { useState } from "react";

export default function ComponentA()
{
    console.log("Component A rendered!");

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

    return(
        
        <>
            <h1>
                Component A
            </h1>
               
            <h2>
                Count is {count}
            </h2>

            <button onClick={() => { setCount(count => count + 1) }}>
                Increase Count
            </button>
        </>
    )
}

And here is ComponentB:

export default function ComponentB()
{
    console.log("Component B rendered!");

    return(
        <>
            <h1>
                Component B
            </h1>
        </>
    )
}

Now, when I re-render ComponentA by clicking the button a bunch of times, I see re-render highlights in ComponentA. But, the surprising part is that I also see highlights in ComponentB.

Here are the highlights:

Image

And here is a Profiler session I recorded:

Image

It clearly shwos that ComponentB also "re-rendered" a bunch of times, and it actually took more time to "re-render" ComponentB than ComponentA.

And here is what the console logs look like:

Image

And indeed, like we expect, there is only the console log when ComponentB rendered the first time and not again. But, the Profiler session and the component render highlights say otherwise.

Now, let's change the structure of App component just a little bit:

import ComponentA from './components/ComponentA';
import ComponentB from './components/ComponentB';

function App() {

	return(

		<div>
			<div>
				<ComponentA />
			</div>

			
			<ComponentB />
			<div>
				
			</div>
		</div>
	);

}

export default App;

And now let's see the component highlights and Profiler session.

Here is the highlights now:

Image

And here is what the Profiler says:

Image

So, now the results are what we expect.

This project was made with React 19, but we also see the same things with React 18 as well. And, the presence or absence of the React Compiler makes no difference.

To verify that the effects are not seen with composition, I made a simple Wrapper component and had the same divs wrap our components as before. Here is the Wrapper:

export default function Wrapper({ children })
{
    return(
        <div>
            { children }
        </div>
    )
}

And now, we use the Wrapper instead of divs in our App component like this:

import Wrapper from './components/Wrapper';

import ComponentA from './components/ComponentA';
import ComponentB from './components/ComponentB';

function App() {

	return(

		<Wrapper>

			<Wrapper>
				<ComponentA />
			</Wrapper>

			

			<Wrapper>
				<ComponentB />
			</Wrapper>

		</Wrapper>
	);

}

export default App;

Thankfully, we do not see the weird behavior in this case. Sigh!

So after all this, we clearly see that the weird stuffs are only seen in a specific case where we are using divs before the composition for layout purposes.

But, I do think that this is not at all "expected React behavior". Either this is a bug with the React library itself, or the React Devtools are lying to us.

So, that was the weird thing I saw. I have also written a blog post where I discuss this same thing in more detail. It can be found here.

How often does this bug happen?

Every time

DevTools package (automated)

No response

DevTools version (automated)

No response

Error message (automated)

No response

Error call stack (automated)


Error component stack (automated)


GitHub query string (automated)


Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions