According to the react documentation,
when setState is called by the user, render is soon after called "behind the scenes". render usually returns a JSX element (though a couple other types are allowed). My question is, since render creates a new JSX element each time, and since setState called on a certain component then calls render on the same component, how is the old state of the components children retained?
I think this question is clear in and of itself, but to illustrate exactly what i mean i will give a toy example.
export class App extends Component {
constructor (props) {
super(props);
this.state = {
foo: [null]
};
this.addToFoo = this.addToFoo.bind(this);
}
addToFoo() {
this.setState(state => {
return {foo: [...state.foo, null]};
});
}
render() {
return (<div onClick={this.addToFoo}>{this.state.foo.map( el => (<Bar></Bar>))}</div>);
}
}
with Bar defined as
export class Bar extends Component {
constructor(props) {
super(props);
this.state = {color: "#111111"};
this.changeColor = this.changeColor.bind(this);
}
changeColor() {
this.setState(state => {
if (state.color === "#111111")
return { color: "#dddddd"}
else
return { color: "#111111"};
})
}
render() {
return (
<div style={{color: this.state.color}} onClick={this.changeColor}>
Howdy!
</div>
);
}
}
Here, when the child is clicked, it toggles its color between a light gray and a dark gray.
When the parent is clicked it changes its state by adding an element to foo.
render is then called on parent behind the scenes, which returns one JSX element that contains foo.length child components of type Bar. However, somehow, the previous state of the children is retained (meaning the colors of the previously included children stay the same, and only the new one is default constructed), even though the foo.length components were newly returned and did not reference the old children at all. How is this possible?