Currently I'm reading the react beta official document.
When I read this part, I'm very confused about the definition of rendering a component in different positions.
// Code from official document
export default function Scoreboard() {
const [isPlayerA, setIsPlayerA] = useState(true);
return (
<div>
// If we use this pattern, the Counter state will not be preserved
{isPlayerA &&
<Counter person="Taylor" />
}
{!isPlayerA &&
<Counter person="Sarah" />
}
// If we use this pattern, the Counter state will be preserved
{/*isPlayerA ? <Counter person="Taylor" /> : <Counter person="Sarah" />*/}
<button onClick={() => {
setIsPlayerA(!isPlayerA);
}}>
Next player!
</button>
</div>
);
}
function Counter({ person }) {
...
}
In the above example, the state in the Counter will be reset because the document said that they will be mount in different positions. However, I'm confused that why they're in different positions? and why another conditional rendering pattern(see the comment above) can preserve state? What's the difference between them?
I've also experimented something, but get confused even more.
export default function Scoreboard() {
const [isPlayerA, setIsPlayerA] = useState(true);
return (
<div>
{isPlayerA && <div>Up</div>}
{isPlayerA ? <Counter person="Taylor" /> : <Counter person="Sarah" />}
{!isPlayerA && <div>Down</div>}
<button onClick={() => {
setIsPlayerA(!isPlayerA);
}}>
Next player!
</button>
</div>
);
}
In the above experiment, the Counter state is preserved also. However, Counter component will be in different position when the isPlayer
state changed.
I think the main thing you're missing is that
false
matters when we're talking about the position of the nodes.This code produces 2 child nodes. If isPlayerA is true, we are outputting a
<Counter>
element, followed byfalse
. If isPlayerA is false, the two children are nowfalse
followed by a<Counter>
element.So since the first child has changed types (Counter -> false), it gets unmounted. And since the second child has changed types (false -> Counter), it mounts.
This code produces 1 child node. If isPlayerA is true, we output a
<Counter>
. If isPlayerA is false, we also output a<Counter>
. Since the type hasn't changed, no unmounting/remounting occurs, and react just updates the props of the existing instance.In this code you have 3 nodes. The first is either false, or a div. The second is always a Counter. The third is either false or a div. Since the second one is always a Counter, it will never remount.