Search code examples
reactjsreduxreact-reduxfetch-apiredux-thunk

Using Async and await with Fetch (in Actions of Redux) ReactJS


I am trying to call several API one after the other, on a button click. something like this. and then Route to a different Path.

 onRowClick = (id) => {
  this.props.selectQuestionnaire(id)
  this.props.getSpecificQuestionnaireAQ(id)
  this.props.getAQoptions(id)
  this.props.getAQResultarray(id)
  history.push('/answerques')
};

All of these are specified as actions in the redux layer, I am using the fetch library to make these API calls An example of one such action is :

export function getAQResultarray(aqid){
  return function(dispatch){
    console.log("fetching specific AQ")
    var myHeaders = new Headers();
    myHeaders.append('Accept' ,  'application/json');
    myHeaders.append('Content-Type' ,  'application/json');
    myHeaders.append('x-Auth-Token' ,  localStorage.getItem('authtoken'));

    const myInit = {
      headers: myHeaders,
      credentials : 'same-origin'
    };

    var url="http://10.00.000.00:000/abc/api/v1/"+aqid
    console.log(url);
    var myRequest = new Request(url)
    fetch(myRequest, myInit)
      .then((response) => {
        console.log("Response for aq responses  notfications : ",response)
        return response.json();
      })
      .then((tokenData) => {
        console.log("posting aq responses specific  : ",tokenData);
        dispatch({
        type : AQ_RESPONSEARRAY,
        payload : tokenData
      })})
      .catch((error) => {
        console.log(error);
      });
  }
};

How do i make this code behave so that, the API calls happen in a synchronous manner? What i mean is, each action is called only after the previous is complete.

I have heard of promise, as well as async/await. Which would e easier to implement?


Solution

  • If I undestand your question correctly you only want to chain the last piece of code, ie redirection. While the actions are perfectly ok to run in parallel. To achive this your action creators should return promises not to break promise chains.

    onRowClick = (id) => {
      // run all actions in parallel
      Promise.all([this.props.selectQuestionnaire(id)
        this.props.getSpecificQuestionnaireAQ(id)
        this.props.getAQoptions(id)
        this.props.getAQResultarray(id)])
      .then(() =>  history.push('/answerques'))
    };
    

    Fix action creators to return promises from thunks.

    export function getAQResultarray(aqid){
      return function(dispatch){
        console.log("fetching specific AQ")
        var myHeaders = new Headers();
        myHeaders.append('Accept' ,  'application/json');
        myHeaders.append('Content-Type' ,  'application/json');
        myHeaders.append('x-Auth-Token' ,  localStorage.getItem('authtoken'));
    
        const myInit = {
          headers: myHeaders,
          credentials : 'same-origin'
        };
    
        var url="http://10.00.000.00:000/abc/api/v1/"+aqid
        console.log(url);
        var myRequest = new Request(url)
    
        // NB! return statement
        return fetch(myRequest, myInit)
          .then((response) => {
            console.log("Response for aq responses  notfications : ",response)
            return response.json();
          })
          .then((tokenData) => {
            console.log("posting aq responses specific  : ",tokenData);
            dispatch({
            type : AQ_RESPONSEARRAY,
            payload : tokenData
          })})
          .catch((error) => {
            console.log(error);
          });
      }
    };
    

    If you actually want to run actions one after another (but I doubt you really need it) you could better stick to async/await syntax at least in handler. But anyway your action creator's thunks should finally return a promise.

    onRowClick = async (id) => {    
      await this.props.selectQuestionnaire(id)
      await this.props.getSpecificQuestionnaireAQ(id)
      await this.props.getAQoptions(id)
      await this.props.getAQResultarray(id)
      history.push('/answerques')
    };