Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React's rule about a different component instance at the same position is treated as the same component [duplicate]

Tags:

reactjs

This may be a somewhat advanced question:

React says: if there are two <Counter /> components but if any one is at the same DOM tree position, it is treated as the same component, and so there is no unmounting and the state will stay:

The React docs: https://react.dev/learn/preserving-and-resetting-state#same-component-at-the-same-position-preserves-state

The code:

export default function App() {
  const [isFancy, setIsFancy] = useState(false);
  return (
    <div>
      {isFancy ? (
        <Counter isFancy={true} /> 
      ) : (
        <Counter isFancy={false} /> 
      )}
      <label>
        <input
        ...

(Note: not that we would write code like that. In real life we'd probably write only one line: <Counter isFancy={isFancy} />, but this is just to show the effect.)

I also put two demos on Codesandbox. Written in a similar way, and confirms with what the docs say:

https://codesandbox.io/p/sandbox/romantic-clarke-wtzdcc?file=%2Fsrc%2FApp.js

https://codesandbox.io/p/sandbox/rough-fast-d29rn7?file=%2Fsrc%2FApp.js

It appears as a strange rule, because they are really two instances, but if that is how React works, so be it.

However, if I try to write it in a slightly different way:

https://codesandbox.io/p/sandbox/musing-sea-mz3qq4?file=%2Fsrc%2FApp.js

  return (
    <div className="App">
      {isFancy && <Counter isFancy={true} />}
      {!isFancy && <Counter isFancy={false} />}
      {theToggle}
    </div>
  );

Then all of a sudden, the counter will reset itself if I toggle "Fancy or not". (if I increase the count to 3, and toggle it. Now the count will reset to 0).

Why is that?

P.S. More thinking into it:

Really, every time App is re-rendered, Counter really is a brand new created instance, even if it is as simple as:

return <Counter isFancy={isFancy} />;

so React doesn't care if it is a new instance. It only cares if it is a component with this name at this position.

like image 797
Stefanie Gauss Avatar asked Oct 24 '25 06:10

Stefanie Gauss


1 Answers

I might be totally wrong, but I think that there is a difference for react

In this example:

<div className="App">
  {isFancy && <Counter isFancy={true} />}
  {!isFancy && <Counter isFancy={false} />}
  {theToggle}
</div>

React will see:

[false, Counter component, some jsx]

And here:

<div className="App">
  {isFancy ? <Counter isFancy={true} /> : <Counter isFancy={false} />}
  {theToggle}
</div>
[Counter component, some jsx]

I know that the docs clearly say that:

it’s the position in the UI tree — not in the JSX markup—that matters to React!

but maybe they meant something different with UI tree

like image 142
Konrad Linkowski Avatar answered Oct 26 '25 06:10

Konrad Linkowski



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!