简体   繁体   中英

React not passing state to child via props

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, ie 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.

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.

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**;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM