Reputation: 7735
I am trying to pass my parent App
state to a child component Chart
.
App
constructor() {
super();
this.state = {
dataPoints: {
'424353': {
date: '10/10/2016',
qty: '95'
},
'535332': {
date: '10/11/2016',
qty: '98'
},
'3453432': {
date: '10/01/2017',
qty: '94'
}
}
};
this.addPoint = this.addPoint.bind(this);
}
addPoint(dataPoint) {
let dataPoints = {...this.state.dataPoints};
const timestamp = Date.now();
dataPoints[timestamp] = dataPoint;
this.setState({ dataPoints: dataPoints });
console.log('new state', this.state.dataPoints);
}
render() {
return (
<div className="app">
<Chart dataPoints={this.state.dataPoints} />
<FormControl addPoint={this.addPoint} />
</div>
);
}
Chart
composeData() {
Object
.keys(this.props.dataPoints)
.forEach(key => {
** do stuff **
});
return **stuff**;
}
componentWillUpdate() {
this.composeData();
}
The addPoint
method works, i.e. I can see in the React console that the new datapoint is added to the state. But it is not reflected in the Chart
component. More oddly (to me) is the fact that when I've added a point, the console.log
line in my addPoint
method (above):
console.log('new state', this.state.dataPoints)
does not show the new data point.
Upvotes: 1
Views: 273
Reputation: 104529
Because setState
is asynchronous
, use this you see the updated values:
this.setState({ dataPoints: dataPoints }, () => {
console.log('new state', this.state.dataPoints);
});
Second thing is, whenever any change happen to props
values, componentWillReceiveProps
lifecycle method will get called, do the computation in this method once you add the new item. Like this:
componentWillReceiveProps(newProps) {
console.log('update props values', newProps);
Object
.keys(newProps.dataPoints)
.forEach(key => {
** do stuff **
});
return **stuff**;
}
Check this answer for complete explanation: why setState is asynchronous.
Upvotes: 1
Reputation: 282040
In add point
addPoint(dataPoint) {
let dataPoints = {...this.state.dataPoints};
const timestamp = Date.now();
dataPoints[timestamp] = dataPoint;
this.setState({ dataPoints: dataPoints });
console.log('new state', this.state.dataPoints);
}
In the above code you do not see the updated value because setState takes time to mutate, You must log it in the setState call back
this.setState({ dataPoints: dataPoints }, function(){
console.log('new state', this.state.dataPoints);
});
And also in the Chart component you need to bind the composeData function if you are using this.props
inside it like
composeData = () =>{
Object
.keys(this.props.dataPoints)
.forEach(key => {
** do stuff **
});
return **stuff**;
}
However componentWillMount
is only called once and hence you will want to call the composeData
function from componentWillReceiveProps
also like
componentWillReceiveProps(nextProps) {
this.composeData(nextProps)
}
componentWillMount() {
this.composeData(this.props.dataPoints)
}
composeData(props){
Object
.keys(props.dataPoints)
.forEach(key => {
** do stuff **
});
return **stuff**;
}
Upvotes: 1