2

I am new to ReactJS. I have created a service that I have called inside componentWillMount() since I want the data as soon as the page loads. Now I want to use the same service when there is a dropdown change and update with the new value. I have called the service inside onChangeDropDown() but it appears that updated value is not rendered correctly.

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
import config from '../../../../config';
import {
Container, Divider, Accordion, Icon, Transition, Label, Table
} from 'semantic-ui-react';

import Utilities, { Button, PtInput, PtInputShort, PtInputIcon, PtSelect, PtDateInput, PtInputConditionTab, PtInputNextToEachOther } from '../../../../grit-utilities';
import ScrollArea from 'react-scrollbar';

export default class Future extends Component {
constructor(props) {
    super(props);
    this.state = {
        ...this.props.futureModel.pavementcondition,
        selectedYear: new Date().getFullYear(),
        PQI: 'N.A.',
        Age: 'N.A.',
        Aadt: 'N.A.',
        Esals: 'N.A.',
        CumEsals: 'N.A.',
        pqiArray: []
    };


}
  getYearOptions = () => {
    const yearOptions = [];
    for (let i = 0; i < 35; i++) {
        yearOptions.push({ key: new Date().getFullYear() + i, value: new Date().getFullYear() + i, label: new Date().getFullYear() + i});
    }
    return yearOptions;
}
  fetchProjectionData = (selectedYear) => {
      axios.get(`${config.server}\\fetchFutureData\\${this.props.futureModel.route.id}\\${selectedYear}`).
          then((res) => {
              if (res.data.result[0]) {
                  let data = res.data.result[0];
                  this.setState({
                      //PQI: data.PSR,
                      Age: data.Age,
                      Esals: data.Esals,
                      Aadt: data.AADT,
                      CumEsals: data.CumEsal
                  });
              }

          });
  }
  render() {
      const yearOptions = this.getYearOptions();

    return (
        <Container>
            <ScrollArea
                speed={1}
                className={!window.mobileAndTabletcheck() ? "area_desktop" : "area_mobile"}
                contentClassName="content"
                smoothScrolling={true}>
                <PtSelect name="selectedYear" defaultVal={this.state.selectedYear} label="Select Year" options={yearOptions} onChange={this.onChangeDropdown.bind(this)} />

                <PtInput disabled placeholder="Not Available" name="PQI" value={this.state.PQI ? this.state.PQI:''} label="PQI - Pavement Quality Index" disabled name="PQI" />

                <PtInput disabled placeholder="Not Available" name="Age" value={this.state.Age ? this.state.Age:''} label="Age" disabled name="Age" />

                <PtInput disabled placeholder="Not Available" name="Aadt" value={this.state.Aadt ? Math.round(this.state.Aadt) : ''} label="AADT" disabled name="AADT" />

                <PtInput disabled placeholder="Not Available" name="Esals" value={this.state.Esals ? Math.round(this.state.Esals):''} label="ESALs" disabled name="ESALs" />

                <PtInput disabled placeholder="Not Available" name="CumEsals" value={this.state.CumEsals ? Math.round(this.state.CumEsals) : ''} label="Cumulative ESALs" disabled name="CumESALs" />



            </ScrollArea>
        </Container>
    );
  }


/* This function actually gets the PQI value for the current year based on routeId and year from FutureTabView hard table

Date: 09/25/2019
*/
getfirstPQI = () =>{

    fetch(`${config.server}/getfirstpqi/`+this.props.futureModel.route.id+`/`+this.state.selectedYear)
     .then(response=>response.json())
     .then(data=>{
         //console.log(data[0]['PSR'])
         this.setState({PQI:data[0]['PSR']})
     })
}




  onChangeDropdown = (e) => {
      const { target } = e;
      const { name, value } = target;

      this.setState({ [name]: parseInt(value) });
      this.fetchProjectionData(value);
      this.getfirstPQI();





  }
  componentDidMount() {
      this.fetchProjectionData(this.state.selectedYear);
      this.getfirstPQI();


  }

}

I have done this code and what I am trying to do it as soon as the page loads it should show the value that is being received from the service. Example: the current year is 2019 and as soon as the page loads the value for the year 2019 is being rendered. Now I have a dropdown of years.So when I choose 2020 the value is not getting updated whereas when I choose 2021 it updates the value with the value of 2020. So the updating value is delaying always. How to render the value as soon as there is a change in dropdown?

user6565467
  • 49
  • 1
  • 9
  • I am sorry, i didn't get your question! – user6565467 Sep 27 '19 at 14:50
  • The `selectedYear` value which comes from the state, where it is updated? Is it always the same ? – Nicolae Maties Sep 27 '19 at 14:52
  • I have edited the code. Is that you were asking for? – user6565467 Sep 27 '19 at 14:54
  • So, when you are loading the component, your `selectedYear` will be 2019, which is the current year, if you are gonna change the year to 2020, where you are fetching again the updated values, what `fetchProjectionData` does? – Nicolae Maties Sep 27 '19 at 14:59
  • You need to post the component that is making the change so we can see the complete process you have set up, as well as what ```getFirstPQI``` is doing. This is probably caused by improper handling of async operations. Also, ```componentWillMount``` is deprecated and you should replaced it with ```componentDidMount()``` – Chris B. Sep 27 '19 at 15:05
  • I have posted the whole code of the react page. If you can please let me know what is going wrong its really appreciated – user6565467 Sep 27 '19 at 15:17

1 Answers1

1

React's setState() is asynchronous, meaning if you want to access the updated state after setting it then you should use the callback which runs when the state has successfully updated.

this.setState({ [name]: parseInt(value) }, () => {
  this.fetchProjectionData(value);
  this.getfirstPQI();
});

If you don't use the callback then getfirstPQI() may be reading the old state.

MrCode
  • 63,975
  • 10
  • 90
  • 112
  • Thank you so much. It worked. I am very new to react actually. So i didn't know that to use the updated state I have to call the function inside the setState that will actually update the values as well. I thought that setState is used to set any new values in front end only. Thank you so much – user6565467 Sep 27 '19 at 15:45