I'm checking react reconciliation. It says that when traversing the children, React will iterate over both lists of children at the same time and generate a mutation whenever there’s a difference.
I made a simple example:
class ComponentA extends React.Component {
state = {
first: true
}
clickHandler = () => {
this.setState({
first: !this.state.first
})
}
render() {
return (
<div className='top'>
{this.state.first ? <span>xyz</span> : undefined}
<div>abc</div>
<div>efg</div>
<button onClick={this.clickHandler}>click me</button>
</div>)
}
}
On click, the first child (span element) will get in and out of the list of children. From React's point of view, iterating one by one, it should look like all elements have changed. Therefore React should re-render the DOM for all of these 4 children (including button).
But checking the DOM inspector in Firefox and Chrome I see highlight only on the span element, not on all four, meaning the DOM is preserved for the three unchanged elements. Why?
(highlight is not seen on this picture but the span element gets highlighted on button click)
What happens in my example is that the first child (the span
) is never really removed from the children array but only toggles between span
and undefined. So there are always 4 children and the reorder (index shifting) never happens.
That's why react knows to match the elements and update only span DOM
element and leave the other 3 as they are.