Using request/success/failure pattern in Redux to handle async actions (Part 1/2)
By: Sunil Chaudhary
Tags: Productivity, Redux, JavaScript, Frontend, React

A lot of times while making the API calls, we face the challenge; where based on different points of time of API call, we need to show different UI or handle other scenarios in a project. There are a lot of approaches to do the same. However, there is one which is the best and is widely used in many organizations. We will discuss about the same in this article.

This is a 2 part article where we will see what is this pattern and how by using capabilities of javascript we can modify this pattern to scale our project easily and keep the code clean in the longer run.

The pattern!

When any async action or API call is made, there are mainly 3 states:

Request State — The async action or API call is in process Success State — The async action or API call is successful and gets some data Failure State — The async action or API call is errored/failed due to some reasons

Based on these 3 states, we create functions and follow certain conventions etc to achieve the desired result.

Things needed here:

action functions type strings reducer function(s)

We pick the main action verb here and append request/success/failure at the end to follow consistent naming convention.

Let’s take an example where we will be making an API call to get a list of users. For each of above listed cases, we will create an action and a type each. Corresponding to cases in above list for get list of users, we have now the following actions and types now:

And the corresponding reducer and the initial state will look something like this:

How it works

When we need to make an api call we will dispatch the request action. It will make isLoading to true and we can use it to show an appropriate message/loader in the screen. As soon as the api call is finished; it will either be in successful or failure state. For each of these, we will dispatch either success or failure which will update the data in the reducer (in data or error variables respectively) as well as make isLoading to false and loaded to true.

The various variables such as isLoading, loaded etc can be now be used in our component for the desired interactions or functionalities.

Why to stick to this pattern

There are several advantages for this pattern and it closely follows all the good practices recommended in any software development. Few of them are:

Readability and Maintainability: Since we are following a fixed pattern for naming, code becomes a lot more readable. request/success/failure model communicates properly the state in which API is and reduces mental overhead. Code Scalability: This structure is highly scalable. We will see how in our next article where we will reuse this structured format to extend this pattern for multiple API calls and avoid a lot of code repetition. Control and Precise Hooks: This pattern also gives us more control. Once implemented, we have hooks at various point in API call to update the UI. Variables like isLoading and loaded give us control over UI whereas actions give control over how to save data in reducer.

Integrating the pattern with middlewares

The pattern also fits in very nicely which libraries such as redux-thunk or redux-saga.

An example here will demonstrate on how to use the same with redux-saga:

and the same can be done easily with thunk as well.

Adding additional actions/types (if needed)

There could be some scenarios where devs might need to reset the data to initial state. In that case, we can add additional action accordingly.

That’s it about the pattern. So simple and sleek and yet so powerful!!

Extending the pattern for multiple API calls

The same approach can be extended now for multiple API calls. The only issue is that if one have a lot of api calls, there will be 3 actions, 3 types and 1 reducer per API call. It means that there will be a lot of repetitive code involved and there will be multiple reducers and logic to merge them.

Well, not to worry about; we can simplify this by using the functional nature of javascript.

For now, Part 1 of the article ends here. Keep following this space and I will update the link for Part 2 in here shortly!

Edit: click here to read Part 2