I'm trying to learn ReactJS and found out about these lifecycles. However I've a doubt regarding how componentDidUpdate() functions and I want to know the reason behind it. Please take a look at the code below. It is a simple code that calculates the area of a triangle. Just to understand how we can send data from parent to child and vice versa I'm initialising the variables in parent component, then passing them to child to calculate the area and then passing back the results to change the state to final one where the results are rendered.
App.js
class App extends React.Component{
constructor(props){
super(props);
console.log("In the parent's constructor");
let initializeState=[{'base' : 0,'height' : 0,'area' : 0}];
this.state={ values : initializeState }
console.log(this.state.values);
}
componentDidMount(){
console.log("Mounting values");
let b = [{}];
b['base']=10;
b['height']=20;
b['area']=0;
this.setState({values: b});
}
update = (base,height,area) => {
console.log("Updating state with calculated area");
let updatedValue = [{}];
updatedValue['base'] = base;
updatedValue['height'] = height;
updatedValue['area'] = area;
this.setState({values: updatedValue});
}
render(){
console.log('Inside Parent render');
return(<React.Fragment>
<Triangle val = {this.state.values} update={this.update} />
</React.Fragment>
)
}
}
class Triangle extends React.Component{
shouldComponentUpdate(newProps, newState){
console.log('validating data');
if(newProps.val.base >0 && newProps.val.height >0){
return true;
}else{
return false;
}
}
componentDidUpdate(prevProps, prevState, snapshot){
console.log('In the child componentDidUpdate');
console.log('If you\'ve reached this, state has been re-rendered')
console.log(prevProps.val.base);
console.log(prevProps.val.height);
console.log(prevProps.val.area);
}
calcArea = () => {
console.log('Calculating area now');
let area = 1/2* this.props.val.base * this.props.val.height;
this.props.update(this.props.val.base,this.props.val.height,area);
}
render(){
console.log("In the child's render method")
return(
<React.Fragment>
<h2>Base : {this.props.val.base}</h2>
<h2>Height : {this.props.val.height}</h2>
<h2>Area : {this.props.val.area} </h2>
<button onClick={this.calcArea}>Click to calculate AREA</button>
</React.Fragment>
)
}
}
export default App;
So Everything is working fine, i.e., This is the series of output:
In the parent's constructor
App.js:11 [{…}]
App.js:33 Inside Parent render
App.js:66 In the child's render method
App.js:15 Mounting values
App.js:33 Inside Parent render
App.js:43 validating data
App.js:66 In the child's render method
App.js:52 In the child componentDidUpdate
App.js:53 If you've reached this, state has been re-rendered
Now till this point, the component has re-rendered according to the new values mentioned inside componentDidMount function. However the next output is :
App.js:54 undefined
App.js:55 undefined
App.js:56 undefined
It should be the values that have been destroyed. ie., 0, 0, 0 (mentioned inside the parent's constructor using this.state ). Though when I hit the calculate Area and the component is re-rendered, it shows the correct values which have been destroyed. ie.,
Calculating area now
App.js:24 Updating state with calculated area
App.js:33 Inside Parent render
App.js:43 validating data
App.js:66 In the child's render method
App.js:52 In the child componentDidUpdate
App.js:53 If you've reached this, state has been re-rendered
App.js:54 10
App.js:55 20
App.js:56 0
Can someone tell me why the results are "undefined" when the state is being changed for the first time and not the values that we have instantiated ??