javascript - How can I wait until the functions finish in Reactjs? - Stack Overflow

Hi I am new to reactjs and I am trying to build button with a function doing some calculation by Reactj

Hi I am new to reactjs and I am trying to build button with a function doing some calculation by Reactjs. The logic is, first I will get two lists from database by two functions. After these 2 functions return results and setState, the calculate function will continue and do its job. But somehow the state is not being updated and it will crash. How can I secure the state is being updated before to the calculate? Thanks a lot!

Code:

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      dividendList : [],
      divisorList : [],
};
}
  getDividend(){
    var self = this;
    axios.post(SERVER_NAME + 'api/getDividend', {})
        .then(function(response){
          let results = response.data;
          console.log(results)
          self.setState({ dividendList : results.data})
        })
        .catch(function(err){
          console.log(err)
        });
  } 
  getDivisor(){
    var self = this;
    axios.post(SERVER_NAME + 'api/getDivisor', {})
        .then(function(response){
          let results = response.data;
          console.log(results)
          self.setState({ divisorList : results.data})
        })
        .catch(function(err){
          console.log(err)
        });
  }

  doCal = () => {
    var self = this;
    self.getDividend();
    self.getDivisor();
    const { dividendList , divisorList} = self.state;
    # then will loop the list and do math
    # but since the state is not update, both lists are empty []
}

Tried Promise;

   getDivisor(){
    var self = this;
    return new Promise((resolve, reject) => {
      axios.post(SERVER_NAME + 'api/draw/getDivisor', {})
      .then(function(response){
        resolve(response)
      })
      .catch(function(err){
        resolve();
      });
    }) 
  } 

Hi I am new to reactjs and I am trying to build button with a function doing some calculation by Reactjs. The logic is, first I will get two lists from database by two functions. After these 2 functions return results and setState, the calculate function will continue and do its job. But somehow the state is not being updated and it will crash. How can I secure the state is being updated before to the calculate? Thanks a lot!

Code:

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      dividendList : [],
      divisorList : [],
};
}
  getDividend(){
    var self = this;
    axios.post(SERVER_NAME + 'api/getDividend', {})
        .then(function(response){
          let results = response.data;
          console.log(results)
          self.setState({ dividendList : results.data})
        })
        .catch(function(err){
          console.log(err)
        });
  } 
  getDivisor(){
    var self = this;
    axios.post(SERVER_NAME + 'api/getDivisor', {})
        .then(function(response){
          let results = response.data;
          console.log(results)
          self.setState({ divisorList : results.data})
        })
        .catch(function(err){
          console.log(err)
        });
  }

  doCal = () => {
    var self = this;
    self.getDividend();
    self.getDivisor();
    const { dividendList , divisorList} = self.state;
    # then will loop the list and do math
    # but since the state is not update, both lists are empty []
}

Tried Promise;

   getDivisor(){
    var self = this;
    return new Promise((resolve, reject) => {
      axios.post(SERVER_NAME + 'api/draw/getDivisor', {})
      .then(function(response){
        resolve(response)
      })
      .catch(function(err){
        resolve();
      });
    }) 
  } 
Share Improve this question edited Dec 1, 2020 at 3:53 WILLIAM asked Dec 1, 2020 at 3:11 WILLIAMWILLIAM 4852 gold badges8 silver badges36 bronze badges 3
  • for a start return axios.post(... then you can either use async/await (or .then) with Promise.all ... by the way, why are your urls like api//getDivisor ... why the double / – Bravo Commented Dec 1, 2020 at 3:15
  • oh typo, do you mean return the axios response data and setstate in doCal function? – WILLIAM Commented Dec 1, 2020 at 3:21
  • if you want to wait until axio.post pletes, you'll need to return that in those functions, then you can use either of the methods in the previous ment inside doCal – Bravo Commented Dec 1, 2020 at 3:34
Add a ment  | 

3 Answers 3

Reset to default 1

I think the issue here is self.getDividend(); and self.getDivisor(); are async operations. They will take some time to plete. By the time you hit the next line const { dividendList , divisorList} = self.state;, these operations are not plete and you will end up getting empty lists.

One way to address this is using moving your doCal function logic after getDividend and getDivisor are pleted. You can also execute these in parallel instead of in a sequence. I used async format instead of .then(). It is just a sysntatic sugar. You can achieve the same using .then() if you prefer that way

async function doCalc() {
  const prom1 = axios.get('https://..dividentList');
  const prom2 = axios.get('https://..divisorList');
  const results = await Promise.all([ prom1, prom2]); // wait for both promise to plete
  // look inside results to get your data and set the state
  // continue doCal logic

}

Using .then()

request1('/dividentList')
.then((res) => {
    //setState for divident
    return request2('/divisorList'); // this will return a promise to chain on
})
.then((res) => {
    setState for divisor
    return Promise.resolve('Success') // we send back a resolved promise to continue chaining
})
.then(() => {
    doCalc logic
})
.catch((err) => {
    console.log('something went wrong');
});

I looked at your code and thought it should be changed like this to be correct.

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      dividendList: [],
      divisorList: [],
    };
  }

  ponentDidMount() {
    // the API just need be called once, so put here
    this.getDividend()
    this.getDivisor()
  }

  ponentDidUpdate(_, prevState) {
    const { dividendList , divisorList } = this.state;
    // Ensure that the answer is only calculated once
    // the answer is only be calculated while the two list data are obtained
    if (
      prevState.divisorList.length === 0 &&
      prevState.dividendList.length === 0 &&
      divisorList.length > 0 &&
      dividendList.length > 0
    ) {
      doCal()
    }
  }

  getDividend(){
    var self = this;
    axios.post(SERVER_NAME + 'api/getDividend', {})
        .then(function(response){
          let results = response.data;
          console.log(results)
          self.setState({ dividendList : results.data})
        })
        .catch(function(err){
          console.log(err)
        });
  } 
  getDivisor(){
    var self = this;
    axios.post(SERVER_NAME + 'api/getDivisor', {})
        .then(function(response){
          let results = response.data;
          console.log(results)
          self.setState({ divisorList : results.data})
        })
        .catch(function(err){
          console.log(err)
        });
  }

  doCal = () => {
    const { dividendList , divisorList } = this.state;
    # then will loop the list and do math
    # but since the state is not update, both lists are empty []

    this.setState({ answer: 'xxx' })
  }

  render() {
    const { dividendList, divisorList, answer } = this.state

    if (dividendList.length === 0 && divisorList.length === 0) {
      return <div>Loading...</div>
    }

    if (!answer) {
      return <div>Error</div>
    }

    return <div>{answer}</div>
  }
}

The following are just some suggestions to make the code easier to read,

  1. you can use arrow function so that you don't need to write self.setState({...})
getDividend = () => {
  axios.post(SERVER_NAME + 'api/getDivisor', {})
    .then((response) => {
      let results = response.data;
      console.log(results)
      this.setState({ divisorList : results.data})
    })
    .catch((err) => {
      console.log(err)
    });
}
  1. and you can also use async/await instead of promise.then
getDividend = async () => {
  const response = await axios.post(SERVER_NAME + 'api/getDivisor', {})  
  let results = response.data;
  console.log(results)
  this.setState({ divisorList : results.data})
}

Set 'dividendList' and 'divisorList' equals to 'null' by default. Then, when a function that uses those lists is called, make a if statement to verify if those states goes for false (if they are still null) then return inside the function, if not, it should not crash anything.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745243452a4618302.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信