How to make the axios call only after the react state is mutated?












0















The react state value this.state.condition is getting passed to axios call , but this.state.condition is mutated only on the second attempt of execution of function generateReport(), so that this.state.condition is passed as an empty array to an axios call on first attempt of the execution of the function generateReport(). Is there any work-around or solution to the problem?
The code is given below.



generateReport(){
this.setState({statusMsg: ""});
this.setState({loaderInitialStatus:"Processing..."})
//this.isReq() ?
console.log('this.state.selectedOption???',this.state.selectedOption);
if(this.state.selectedOption && this.state.selectedOption.length > 0) {
let groups =
this.state.selectedOption.map((item) => {
groups.push(item.value);
})
this.setState(prevState => ({
condition: [...prevState.condition, { name: "readByGroup", operator: "IN ", value: groups }]
}))
}
console.log('this.state.condition???', this.state.condition);

this.props.getMetricsByContent(this.state.condition).then((data) => {
this.setState({isLoader: false});
if(data && Array.isArray(data) && data.length > 0){
let csvContent = papa.unparse(data);
this.download(csvContent, 'metrics.csv', 'text/csv;encoding:utf-8');
this.setState({statusMsg: "File Downloaded successfully"})
} else this.setState({statusMsg: "No records to download"})
})

//: null;

}









share|improve this question


















  • 1





    Store the new condition object in variable instead and pass that in to the function. Or call getMetricsByContent() in the setState callback above it. Setting state is not synchronous

    – charlietfl
    Nov 23 '18 at 3:22













  • Can you wrap your axios call in a conditional? That way it won't execute until the 2nd execution of generateReport if(this.state.condition) { ...axios call... }

    – Shawn Andrews
    Nov 23 '18 at 3:24













  • where are you mutating this.state.condition? This can help stackoverflow.com/questions/36085726/…

    – Vivek
    Nov 23 '18 at 4:20


















0















The react state value this.state.condition is getting passed to axios call , but this.state.condition is mutated only on the second attempt of execution of function generateReport(), so that this.state.condition is passed as an empty array to an axios call on first attempt of the execution of the function generateReport(). Is there any work-around or solution to the problem?
The code is given below.



generateReport(){
this.setState({statusMsg: ""});
this.setState({loaderInitialStatus:"Processing..."})
//this.isReq() ?
console.log('this.state.selectedOption???',this.state.selectedOption);
if(this.state.selectedOption && this.state.selectedOption.length > 0) {
let groups =
this.state.selectedOption.map((item) => {
groups.push(item.value);
})
this.setState(prevState => ({
condition: [...prevState.condition, { name: "readByGroup", operator: "IN ", value: groups }]
}))
}
console.log('this.state.condition???', this.state.condition);

this.props.getMetricsByContent(this.state.condition).then((data) => {
this.setState({isLoader: false});
if(data && Array.isArray(data) && data.length > 0){
let csvContent = papa.unparse(data);
this.download(csvContent, 'metrics.csv', 'text/csv;encoding:utf-8');
this.setState({statusMsg: "File Downloaded successfully"})
} else this.setState({statusMsg: "No records to download"})
})

//: null;

}









share|improve this question


















  • 1





    Store the new condition object in variable instead and pass that in to the function. Or call getMetricsByContent() in the setState callback above it. Setting state is not synchronous

    – charlietfl
    Nov 23 '18 at 3:22













  • Can you wrap your axios call in a conditional? That way it won't execute until the 2nd execution of generateReport if(this.state.condition) { ...axios call... }

    – Shawn Andrews
    Nov 23 '18 at 3:24













  • where are you mutating this.state.condition? This can help stackoverflow.com/questions/36085726/…

    – Vivek
    Nov 23 '18 at 4:20
















0












0








0








The react state value this.state.condition is getting passed to axios call , but this.state.condition is mutated only on the second attempt of execution of function generateReport(), so that this.state.condition is passed as an empty array to an axios call on first attempt of the execution of the function generateReport(). Is there any work-around or solution to the problem?
The code is given below.



generateReport(){
this.setState({statusMsg: ""});
this.setState({loaderInitialStatus:"Processing..."})
//this.isReq() ?
console.log('this.state.selectedOption???',this.state.selectedOption);
if(this.state.selectedOption && this.state.selectedOption.length > 0) {
let groups =
this.state.selectedOption.map((item) => {
groups.push(item.value);
})
this.setState(prevState => ({
condition: [...prevState.condition, { name: "readByGroup", operator: "IN ", value: groups }]
}))
}
console.log('this.state.condition???', this.state.condition);

this.props.getMetricsByContent(this.state.condition).then((data) => {
this.setState({isLoader: false});
if(data && Array.isArray(data) && data.length > 0){
let csvContent = papa.unparse(data);
this.download(csvContent, 'metrics.csv', 'text/csv;encoding:utf-8');
this.setState({statusMsg: "File Downloaded successfully"})
} else this.setState({statusMsg: "No records to download"})
})

//: null;

}









share|improve this question














The react state value this.state.condition is getting passed to axios call , but this.state.condition is mutated only on the second attempt of execution of function generateReport(), so that this.state.condition is passed as an empty array to an axios call on first attempt of the execution of the function generateReport(). Is there any work-around or solution to the problem?
The code is given below.



generateReport(){
this.setState({statusMsg: ""});
this.setState({loaderInitialStatus:"Processing..."})
//this.isReq() ?
console.log('this.state.selectedOption???',this.state.selectedOption);
if(this.state.selectedOption && this.state.selectedOption.length > 0) {
let groups =
this.state.selectedOption.map((item) => {
groups.push(item.value);
})
this.setState(prevState => ({
condition: [...prevState.condition, { name: "readByGroup", operator: "IN ", value: groups }]
}))
}
console.log('this.state.condition???', this.state.condition);

this.props.getMetricsByContent(this.state.condition).then((data) => {
this.setState({isLoader: false});
if(data && Array.isArray(data) && data.length > 0){
let csvContent = papa.unparse(data);
this.download(csvContent, 'metrics.csv', 'text/csv;encoding:utf-8');
this.setState({statusMsg: "File Downloaded successfully"})
} else this.setState({statusMsg: "No records to download"})
})

//: null;

}






javascript reactjs asynchronous axios






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 23 '18 at 3:18









PremPrem

1,70382653




1,70382653








  • 1





    Store the new condition object in variable instead and pass that in to the function. Or call getMetricsByContent() in the setState callback above it. Setting state is not synchronous

    – charlietfl
    Nov 23 '18 at 3:22













  • Can you wrap your axios call in a conditional? That way it won't execute until the 2nd execution of generateReport if(this.state.condition) { ...axios call... }

    – Shawn Andrews
    Nov 23 '18 at 3:24













  • where are you mutating this.state.condition? This can help stackoverflow.com/questions/36085726/…

    – Vivek
    Nov 23 '18 at 4:20
















  • 1





    Store the new condition object in variable instead and pass that in to the function. Or call getMetricsByContent() in the setState callback above it. Setting state is not synchronous

    – charlietfl
    Nov 23 '18 at 3:22













  • Can you wrap your axios call in a conditional? That way it won't execute until the 2nd execution of generateReport if(this.state.condition) { ...axios call... }

    – Shawn Andrews
    Nov 23 '18 at 3:24













  • where are you mutating this.state.condition? This can help stackoverflow.com/questions/36085726/…

    – Vivek
    Nov 23 '18 at 4:20










1




1





Store the new condition object in variable instead and pass that in to the function. Or call getMetricsByContent() in the setState callback above it. Setting state is not synchronous

– charlietfl
Nov 23 '18 at 3:22







Store the new condition object in variable instead and pass that in to the function. Or call getMetricsByContent() in the setState callback above it. Setting state is not synchronous

– charlietfl
Nov 23 '18 at 3:22















Can you wrap your axios call in a conditional? That way it won't execute until the 2nd execution of generateReport if(this.state.condition) { ...axios call... }

– Shawn Andrews
Nov 23 '18 at 3:24







Can you wrap your axios call in a conditional? That way it won't execute until the 2nd execution of generateReport if(this.state.condition) { ...axios call... }

– Shawn Andrews
Nov 23 '18 at 3:24















where are you mutating this.state.condition? This can help stackoverflow.com/questions/36085726/…

– Vivek
Nov 23 '18 at 4:20







where are you mutating this.state.condition? This can help stackoverflow.com/questions/36085726/…

– Vivek
Nov 23 '18 at 4:20














2 Answers
2






active

oldest

votes


















0














your setting state meanwhile you checking the condition also, so your getting unpredictable output which is wrong. put your logic in callback of setState



please go through bellow code :






generateReport(){
this.setState({statusMsg:"", loaderInitialStatus:"Processing..."}, this.callBack)
}

callBack=()=>{
console.log('this.state.selectedOption???',this.state.selectedOption);
if(this.state.selectedOption && this.state.selectedOption.length > 0) {
let groups =
this.state.selectedOption.map((item) => {
groups.push(item.value);
})
this.setState(prevState => ({
condition: [...prevState.condition, { name: "readByGroup", operator: "IN ", value: groups }]
}))
}
console.log('this.state.condition???', this.state.condition);

this.props.getMetricsByContent(this.state.condition).then((data) => {
this.setState({isLoader: false});
if(data && Array.isArray(data) && data.length > 0){
let csvContent = papa.unparse(data);
this.download(csvContent, 'metrics.csv', 'text/csv;encoding:utf-8');
this.setState({statusMsg: "File Downloaded successfully"})
} else this.setState({statusMsg: "No records to download"})
})
}








share|improve this answer































    0














    The reason for the unexpected behaviour is because this.setState() is asynchronous and doesn't execute immediately as one expects. In this case when setState() is being invoked one after the other, it is not guaranteed that the first setState() executes before the next one. Also, react tries to combine the maximum possible setState() invocations into one there by reducing the virtual DOM re-rendering and lookup for changes.



    So, in this case where we want the operations to be synchronous, we can pass a callback which will execute once the setState() is successful.



    generateReport(){
    const { selectedOption } = this.state;
    if(selectedOption && selectedOption.length > 0) {
    let groups =
    selectedOption.map((item) => {
    groups.push(item.value);
    })
    this.setState(currStaleState => ({
    statusMsg: "", loaderInitialStatus:"Processing...",
    condition: [...currStaleState.condition, { name: "readByGroup", operator: "IN ", value: groups }]
    }), () => {
    this.props.getMetricsByContent(this.state.condition).then((data) => {
    this.setState({isLoader: false});
    if(data && Array.isArray(data) && data.length > 0){
    let csvContent = papa.unparse(data);
    this.download(csvContent, 'metrics.csv', 'text/csv;encoding:utf-8');
    this.setState({statusMsg: "File Downloaded successfully"})
    } else this.setState({statusMsg: "No records to download"})
    })
    })
    } else {
    console.log('error : no option selected');
    }
    }


    Also, I have merged all the setState() invocations which looked independent. Also you should have a else condition in case nothing is selected, just in case it's not handled. because your state would be set to processing forever as it was set in the first line before.



    Hope this solves the issue. Please comment in case of any issues :)






    share|improve this answer























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53440263%2fhow-to-make-the-axios-call-only-after-the-react-state-is-mutated%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      0














      your setting state meanwhile you checking the condition also, so your getting unpredictable output which is wrong. put your logic in callback of setState



      please go through bellow code :






      generateReport(){
      this.setState({statusMsg:"", loaderInitialStatus:"Processing..."}, this.callBack)
      }

      callBack=()=>{
      console.log('this.state.selectedOption???',this.state.selectedOption);
      if(this.state.selectedOption && this.state.selectedOption.length > 0) {
      let groups =
      this.state.selectedOption.map((item) => {
      groups.push(item.value);
      })
      this.setState(prevState => ({
      condition: [...prevState.condition, { name: "readByGroup", operator: "IN ", value: groups }]
      }))
      }
      console.log('this.state.condition???', this.state.condition);

      this.props.getMetricsByContent(this.state.condition).then((data) => {
      this.setState({isLoader: false});
      if(data && Array.isArray(data) && data.length > 0){
      let csvContent = papa.unparse(data);
      this.download(csvContent, 'metrics.csv', 'text/csv;encoding:utf-8');
      this.setState({statusMsg: "File Downloaded successfully"})
      } else this.setState({statusMsg: "No records to download"})
      })
      }








      share|improve this answer




























        0














        your setting state meanwhile you checking the condition also, so your getting unpredictable output which is wrong. put your logic in callback of setState



        please go through bellow code :






        generateReport(){
        this.setState({statusMsg:"", loaderInitialStatus:"Processing..."}, this.callBack)
        }

        callBack=()=>{
        console.log('this.state.selectedOption???',this.state.selectedOption);
        if(this.state.selectedOption && this.state.selectedOption.length > 0) {
        let groups =
        this.state.selectedOption.map((item) => {
        groups.push(item.value);
        })
        this.setState(prevState => ({
        condition: [...prevState.condition, { name: "readByGroup", operator: "IN ", value: groups }]
        }))
        }
        console.log('this.state.condition???', this.state.condition);

        this.props.getMetricsByContent(this.state.condition).then((data) => {
        this.setState({isLoader: false});
        if(data && Array.isArray(data) && data.length > 0){
        let csvContent = papa.unparse(data);
        this.download(csvContent, 'metrics.csv', 'text/csv;encoding:utf-8');
        this.setState({statusMsg: "File Downloaded successfully"})
        } else this.setState({statusMsg: "No records to download"})
        })
        }








        share|improve this answer


























          0












          0








          0







          your setting state meanwhile you checking the condition also, so your getting unpredictable output which is wrong. put your logic in callback of setState



          please go through bellow code :






          generateReport(){
          this.setState({statusMsg:"", loaderInitialStatus:"Processing..."}, this.callBack)
          }

          callBack=()=>{
          console.log('this.state.selectedOption???',this.state.selectedOption);
          if(this.state.selectedOption && this.state.selectedOption.length > 0) {
          let groups =
          this.state.selectedOption.map((item) => {
          groups.push(item.value);
          })
          this.setState(prevState => ({
          condition: [...prevState.condition, { name: "readByGroup", operator: "IN ", value: groups }]
          }))
          }
          console.log('this.state.condition???', this.state.condition);

          this.props.getMetricsByContent(this.state.condition).then((data) => {
          this.setState({isLoader: false});
          if(data && Array.isArray(data) && data.length > 0){
          let csvContent = papa.unparse(data);
          this.download(csvContent, 'metrics.csv', 'text/csv;encoding:utf-8');
          this.setState({statusMsg: "File Downloaded successfully"})
          } else this.setState({statusMsg: "No records to download"})
          })
          }








          share|improve this answer













          your setting state meanwhile you checking the condition also, so your getting unpredictable output which is wrong. put your logic in callback of setState



          please go through bellow code :






          generateReport(){
          this.setState({statusMsg:"", loaderInitialStatus:"Processing..."}, this.callBack)
          }

          callBack=()=>{
          console.log('this.state.selectedOption???',this.state.selectedOption);
          if(this.state.selectedOption && this.state.selectedOption.length > 0) {
          let groups =
          this.state.selectedOption.map((item) => {
          groups.push(item.value);
          })
          this.setState(prevState => ({
          condition: [...prevState.condition, { name: "readByGroup", operator: "IN ", value: groups }]
          }))
          }
          console.log('this.state.condition???', this.state.condition);

          this.props.getMetricsByContent(this.state.condition).then((data) => {
          this.setState({isLoader: false});
          if(data && Array.isArray(data) && data.length > 0){
          let csvContent = papa.unparse(data);
          this.download(csvContent, 'metrics.csv', 'text/csv;encoding:utf-8');
          this.setState({statusMsg: "File Downloaded successfully"})
          } else this.setState({statusMsg: "No records to download"})
          })
          }








          generateReport(){
          this.setState({statusMsg:"", loaderInitialStatus:"Processing..."}, this.callBack)
          }

          callBack=()=>{
          console.log('this.state.selectedOption???',this.state.selectedOption);
          if(this.state.selectedOption && this.state.selectedOption.length > 0) {
          let groups =
          this.state.selectedOption.map((item) => {
          groups.push(item.value);
          })
          this.setState(prevState => ({
          condition: [...prevState.condition, { name: "readByGroup", operator: "IN ", value: groups }]
          }))
          }
          console.log('this.state.condition???', this.state.condition);

          this.props.getMetricsByContent(this.state.condition).then((data) => {
          this.setState({isLoader: false});
          if(data && Array.isArray(data) && data.length > 0){
          let csvContent = papa.unparse(data);
          this.download(csvContent, 'metrics.csv', 'text/csv;encoding:utf-8');
          this.setState({statusMsg: "File Downloaded successfully"})
          } else this.setState({statusMsg: "No records to download"})
          })
          }





          generateReport(){
          this.setState({statusMsg:"", loaderInitialStatus:"Processing..."}, this.callBack)
          }

          callBack=()=>{
          console.log('this.state.selectedOption???',this.state.selectedOption);
          if(this.state.selectedOption && this.state.selectedOption.length > 0) {
          let groups =
          this.state.selectedOption.map((item) => {
          groups.push(item.value);
          })
          this.setState(prevState => ({
          condition: [...prevState.condition, { name: "readByGroup", operator: "IN ", value: groups }]
          }))
          }
          console.log('this.state.condition???', this.state.condition);

          this.props.getMetricsByContent(this.state.condition).then((data) => {
          this.setState({isLoader: false});
          if(data && Array.isArray(data) && data.length > 0){
          let csvContent = papa.unparse(data);
          this.download(csvContent, 'metrics.csv', 'text/csv;encoding:utf-8');
          this.setState({statusMsg: "File Downloaded successfully"})
          } else this.setState({statusMsg: "No records to download"})
          })
          }






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 23 '18 at 4:42









          Sunil KumarSunil Kumar

          795




          795

























              0














              The reason for the unexpected behaviour is because this.setState() is asynchronous and doesn't execute immediately as one expects. In this case when setState() is being invoked one after the other, it is not guaranteed that the first setState() executes before the next one. Also, react tries to combine the maximum possible setState() invocations into one there by reducing the virtual DOM re-rendering and lookup for changes.



              So, in this case where we want the operations to be synchronous, we can pass a callback which will execute once the setState() is successful.



              generateReport(){
              const { selectedOption } = this.state;
              if(selectedOption && selectedOption.length > 0) {
              let groups =
              selectedOption.map((item) => {
              groups.push(item.value);
              })
              this.setState(currStaleState => ({
              statusMsg: "", loaderInitialStatus:"Processing...",
              condition: [...currStaleState.condition, { name: "readByGroup", operator: "IN ", value: groups }]
              }), () => {
              this.props.getMetricsByContent(this.state.condition).then((data) => {
              this.setState({isLoader: false});
              if(data && Array.isArray(data) && data.length > 0){
              let csvContent = papa.unparse(data);
              this.download(csvContent, 'metrics.csv', 'text/csv;encoding:utf-8');
              this.setState({statusMsg: "File Downloaded successfully"})
              } else this.setState({statusMsg: "No records to download"})
              })
              })
              } else {
              console.log('error : no option selected');
              }
              }


              Also, I have merged all the setState() invocations which looked independent. Also you should have a else condition in case nothing is selected, just in case it's not handled. because your state would be set to processing forever as it was set in the first line before.



              Hope this solves the issue. Please comment in case of any issues :)






              share|improve this answer




























                0














                The reason for the unexpected behaviour is because this.setState() is asynchronous and doesn't execute immediately as one expects. In this case when setState() is being invoked one after the other, it is not guaranteed that the first setState() executes before the next one. Also, react tries to combine the maximum possible setState() invocations into one there by reducing the virtual DOM re-rendering and lookup for changes.



                So, in this case where we want the operations to be synchronous, we can pass a callback which will execute once the setState() is successful.



                generateReport(){
                const { selectedOption } = this.state;
                if(selectedOption && selectedOption.length > 0) {
                let groups =
                selectedOption.map((item) => {
                groups.push(item.value);
                })
                this.setState(currStaleState => ({
                statusMsg: "", loaderInitialStatus:"Processing...",
                condition: [...currStaleState.condition, { name: "readByGroup", operator: "IN ", value: groups }]
                }), () => {
                this.props.getMetricsByContent(this.state.condition).then((data) => {
                this.setState({isLoader: false});
                if(data && Array.isArray(data) && data.length > 0){
                let csvContent = papa.unparse(data);
                this.download(csvContent, 'metrics.csv', 'text/csv;encoding:utf-8');
                this.setState({statusMsg: "File Downloaded successfully"})
                } else this.setState({statusMsg: "No records to download"})
                })
                })
                } else {
                console.log('error : no option selected');
                }
                }


                Also, I have merged all the setState() invocations which looked independent. Also you should have a else condition in case nothing is selected, just in case it's not handled. because your state would be set to processing forever as it was set in the first line before.



                Hope this solves the issue. Please comment in case of any issues :)






                share|improve this answer


























                  0












                  0








                  0







                  The reason for the unexpected behaviour is because this.setState() is asynchronous and doesn't execute immediately as one expects. In this case when setState() is being invoked one after the other, it is not guaranteed that the first setState() executes before the next one. Also, react tries to combine the maximum possible setState() invocations into one there by reducing the virtual DOM re-rendering and lookup for changes.



                  So, in this case where we want the operations to be synchronous, we can pass a callback which will execute once the setState() is successful.



                  generateReport(){
                  const { selectedOption } = this.state;
                  if(selectedOption && selectedOption.length > 0) {
                  let groups =
                  selectedOption.map((item) => {
                  groups.push(item.value);
                  })
                  this.setState(currStaleState => ({
                  statusMsg: "", loaderInitialStatus:"Processing...",
                  condition: [...currStaleState.condition, { name: "readByGroup", operator: "IN ", value: groups }]
                  }), () => {
                  this.props.getMetricsByContent(this.state.condition).then((data) => {
                  this.setState({isLoader: false});
                  if(data && Array.isArray(data) && data.length > 0){
                  let csvContent = papa.unparse(data);
                  this.download(csvContent, 'metrics.csv', 'text/csv;encoding:utf-8');
                  this.setState({statusMsg: "File Downloaded successfully"})
                  } else this.setState({statusMsg: "No records to download"})
                  })
                  })
                  } else {
                  console.log('error : no option selected');
                  }
                  }


                  Also, I have merged all the setState() invocations which looked independent. Also you should have a else condition in case nothing is selected, just in case it's not handled. because your state would be set to processing forever as it was set in the first line before.



                  Hope this solves the issue. Please comment in case of any issues :)






                  share|improve this answer













                  The reason for the unexpected behaviour is because this.setState() is asynchronous and doesn't execute immediately as one expects. In this case when setState() is being invoked one after the other, it is not guaranteed that the first setState() executes before the next one. Also, react tries to combine the maximum possible setState() invocations into one there by reducing the virtual DOM re-rendering and lookup for changes.



                  So, in this case where we want the operations to be synchronous, we can pass a callback which will execute once the setState() is successful.



                  generateReport(){
                  const { selectedOption } = this.state;
                  if(selectedOption && selectedOption.length > 0) {
                  let groups =
                  selectedOption.map((item) => {
                  groups.push(item.value);
                  })
                  this.setState(currStaleState => ({
                  statusMsg: "", loaderInitialStatus:"Processing...",
                  condition: [...currStaleState.condition, { name: "readByGroup", operator: "IN ", value: groups }]
                  }), () => {
                  this.props.getMetricsByContent(this.state.condition).then((data) => {
                  this.setState({isLoader: false});
                  if(data && Array.isArray(data) && data.length > 0){
                  let csvContent = papa.unparse(data);
                  this.download(csvContent, 'metrics.csv', 'text/csv;encoding:utf-8');
                  this.setState({statusMsg: "File Downloaded successfully"})
                  } else this.setState({statusMsg: "No records to download"})
                  })
                  })
                  } else {
                  console.log('error : no option selected');
                  }
                  }


                  Also, I have merged all the setState() invocations which looked independent. Also you should have a else condition in case nothing is selected, just in case it's not handled. because your state would be set to processing forever as it was set in the first line before.



                  Hope this solves the issue. Please comment in case of any issues :)







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 23 '18 at 5:25









                  klvenkyklvenky

                  134212




                  134212






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53440263%2fhow-to-make-the-axios-call-only-after-the-react-state-is-mutated%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown