Nirmala Madusanka
Nirmala Madusanka

Reputation: 113

React Native, Redux - How to execute async action after successfully executing another async action

In a react native application, I need to update a list item by executing an async action and after successfully executing the particular update async action, I need to reload the list item respectively with the changes of the above update action. Here I'm reloading the list by executing an async action. I would like to know how to execute two async actions(A and B) sequentially after successfully executing the first one(A) and then the second one (B)

I have implemented a react-native app with redux. Basically it is communicating with an API using web services. I have used Fetch API for implementing async calls and have used a custom implemented Http middleware to handle async calls as a common method(I have not used thunk)

The custom middleware looks like below

    export const commonHttpAction = (action) => {
    const commonHttpActionTemplate = {
        type: '',
        urlParam: null,
        httpMethod: action.requestMethod == undefined ? 'GET' : action.requestMethod,
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + accessToken
        },
        body: action.requestBody == undefined ? undefined : action.requestBody,
        payload: null
    };

    return {
        HTTP_ACTION: Object.assign({}, commonHttpActionTemplate, action)
    };
};
    const httpMiddleware = store => next => action => {
    if(action[HTTP_ACTION]) {
        const actionInfo = action[HTTP_ACTION];
        const fetchOptions = {
            method: actionInfo.httpMethod,
            headers: actionInfo.headers,
            body: actionInfo.body || actionInfo.requestBody || actionInfo.payload || null
        };

        next({
           type: actionInfo.type + "_REQUEST"
        });

        fetch(getHostUrl() + '/' + actionInfo.urlParam, fetchOptions)
            .then(response => response.json())
            .then(responseJson => next({
                type: actionInfo.type + "_SUCCESS",
                payload: responseJson
            }))
            .catch(error => next({
                type: actionInfo.type + "_FAILURE",
                payload: error
            }));
    } else {
        return next(action);
    }
}

export default httpMiddleware;

Then I have dispatched the async actions through mapDispatchToProps and connect() functions in react-native components/screens using the above custom middleware.

Then reducers will handle the response according to action types.

eg:

    ACTION_TYPE_REQUEST, ACTION_TYPE_SUCCESS and ACTION_TYPE_FAILURE

Then in components/screens, I have used "mapStateToProps" function to use the paylod from reducers

As the above-described way, I have fetched data to my screens and Imagine if I have created a Flatlist by dispatching an async action to load the data to the list and I will update one of the list items by dispatching another async action. I need to re-render the Flatlist after successfully finishing update async action. So far I have attempted a callback function. but with my implementation, the list loading async action is not dispatching (Simply the Flatlist is not reloading after one of list items updating).

I have written the callback as below


class ExampleComponent extends Component {
    componentDidMount() {
       this.props.listDataLoadingAction()
    }
    render() {
       return(
         <View>
            <Flatlist
              renderItem={(item) => 
                <View>
                  <TouchableOpacity onPress={() => {this.updateAction, 
                    ()=> this.props.listDataLoadingAction()}}>
                  </TouchableOpacity>
                </View>
              }
            />
         </View>
       );
    }

    updateActon =(callback) => {
      this.props.updateListRecordAction();
      callback();
    }

}

const mapStateToProps = state => {
  return{
    //get the reducer data
  }
}

const mapDispatchToProps = dispatch => {
  return {
   istDataLoadingAction: () => dispatch(istDataLoadingAction()),
   updateListRecordAction: () => dispatch(updateListRecordAction())
  }
}

export default connect(mapstateToProps, mapDispatchToProps)(ExampleComponent)

It will be much appreciated if anyone can come up with a solution

Upvotes: 0

Views: 610

Answers (1)

Arno
Arno

Reputation: 1001

It would really help if you had a code snippet of what it is you're trying to do.

In general though you can use async/await

async function () {
  await firstAction();
  await secondAction();
}

If the first action does not impact the second then I would dispatch and await both

async function () {
  await Promise.all([
    firstAction(),
    secondAction(),
  ]);
}

Upvotes: 1

Related Questions