React Async/Await API layer, with REDUX Sagas
Tags: redux, sagas, async, react
Published: 2020-02-23 09:06:39

---
title: React Async/Await API layer, with REDUX Sagas
published: true
description: Using an API Layer in Redux along with Redux Sagas
tags: Redux, Sagas, Async, React
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/j8ps60vmag7sgo8uh41f.jpg
---
[Photo Cred : Naomi Koelemans](https://unsplash.com/@naomikoelemans)


## Assumptions

- you know how to redux
- you are familiar with async await
- you know a little bit of sagas

I spent at least 4 hours on a saturday night trying to get this to work.

my understanding of async await was shakey at best and i was brand new to sagas - maybe this can help clear the air for you a bit, and give you a practical explanation along with some code examples.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/98022qp2xrhrlxmo7qx7.png)

## Context

So i have this component here. when a user doesn't enter any information, it is informed by an `alertsReducer.js` with errors from the backend.

`alertsReducer.js`

```javascript

import { Users } from '../constants'
const initialState = {}

export function alertsReducer(state = initialState, action) {

  switch (action.type) {
    case Users.handleUserSignupError:
      return {
        ...state,
        data: action.payload.errors
      }
    default:
      return { data: initialState }
  }
}

```

As you can see it needs an `errors` object attached to the payload in order to function correctly.

Cool, now we know what we need to expect - lets go back to the beginning of the request:

In the component it self, i have a simple redux action that gets fired when the user presses submit.

```javascript
...

handleSubmit = (data) => {
  this.props.handleSubmit(data)
}

render() {
  <div>
    <button onClick={handleSubmit}>submit</button>
  </div>
}

...

```

totally a watered down example, but you get the idea, it is calling a redux action, and then in the same component, we are reading the state of the alerts reducer, and when we receive the errors, we funnel it back into the component.

Alright - heres where it gets hairy, trying to figure out sagas, while at the same time abstracting out an `API` layer to make everything nice and neat was my end goal.

establishing an architecture pattern for my redux front end.

`/actions.js`
```javascript
export const sendSignupDetails = (data) => {
  return {
    type: Users.sendSignupDetails,
    payload: data
  }
}

export const signupSuccess = (data) => {
  return {
    type: Users.handleUserSignupSuccess,
    payload: data
  };
}

export const signupError = (errors) => {
  return {
    type: Users.handleUserSignupError,
    error: true,
    payload: errors
  };
}

```

you can see here, when this action fires, it sends the constant action type, and also passes the data into payload!

Okay great , so far so good...

## Enter Sagas

I'm not gonna get into all the hairy details that took at least 4 hours of figuring out, ill just do my best to explain my thinking for how i chose this as the best pattern for my sagas setup...


`/sagas.js`
```javascript

function* sendSignupDetails(action) {
  yield takeLatest(Users.sendSignupDetails, postUserSignup)
}

function* postUserSignup(action) {
  const response = yield call(usersApi.signupUser, action.payload);
  if (response.errors) {
    yield put(signupError(response));
  } else {
    yield put(signupSuccess(response))
  }

}

function* handleUserSignupSuccess(action){
  yield takeLatest(Users.handleUserSignupSuccess, redirectToDashboard)
}
```

of course there is some more setup involved, but I wanted to focus mainly on the sagas themselves....

as you can see `sendSignupDetails` is a watcher, that waits for the correct action to be dispatched, in this case it's the one we set up earlier which is : `Users.sendSignupDetails`

using `takeLatest` it will watch for the latest call of the action. you can google more info on `takeLatest` all over the interwebs.

the first argument of `takeLatest` is the action itself, and the second, is what you want it to do when it sees this action.

here i am calling `function* postUserSignup` , this does a few things.

`yield` is calling an API request for us, and passing our payload into the Api request. we set this equal to a response so that we can grab the insides out and dispatch them off into either a success or error , based on the contents of the response.

notice `if(response.errors)` there are probaly better ways to do this, but if our server returns an `errors` key, which i have it doing , then we will dispatch the `signupError` action we set up earlier in the actions file.

if you can tell me how to get this work with `try catch` please leave comments below, otherwise, do this, cause it has served me well thus far.

## API File

since im a big fan of abstracting things out and making them nice and neat, i have an `/API` file that i `import` into my sagas file, its basically a class that looks like this:

`/API.js`


```javascript
// notice how i am extending a base class here
import Api from './base-api';

export class UsersAPI extends Api {
  signupUser = async (data) => {
    const { user } = data;
    let res = await Api.postRequest('/users', {user})
    let response = await res.json()
    return response
  }
}

```

great, so to make this as neat as possible , I am using `async` on the function definition, and then to handle the responses from the actual API requests , I am using `await`, and then using `await` again to render json out of the initial response.

`/base-api.js`
```javascript

const headers = {
  'Accept': 'application/json',
  'Content-Type': 'application/json'
}

export default class Api {
  static postRequest = (url, data) => {

    const options = {
      method: 'POST',
      headers: headers,
      body: JSON.stringify(data)
    }

    return fetch(url,options)
  }
}

```

I have all of my crud options `CREATE,READ,UPDATE,DELETE` seprated into neat little methods on my base class to clean it up even more.

THATS IT !

1. the `static` method on the base class will return an `fetch` request to my `/API.js` file

2. In `/API.js` I will handle the response from the API using `async/await`

3. once i have a nice clean JSON response, i will send it back to the saga

4. where it will call the action, and pass the payload into the reducer.

Maybe, just maybe this will save someone some time- it took me along time to figure out a pattern that worked, since everything i typed `async/await` in google, it would show me articles like :

> ASYNC AWAIT VS REDUX SAGAS

hahahhaa, well thats all for now, until we meet again! happy coding!!!

Ken