Multi params requests using Axios
Tags: javascript, vue, webdev
Published: 2020-08-29 14:17:36

Axios is an easy and widely used when we talk about fetching data. But have you ever had problems with multi query params?
Let's check how to do it properly then! :)

### **QueryStrings**

Working with QueryStrings, in general, can be an easy task, but sometimes we can face more specific situations that make the game a little bit more tricky.

Okay, but what the heck is a QueryString??
You may have seen some URLs that have the following format:

_https://www.yourdomain.com/user?id=3_

QueryStrings are part of the URL that contain an information that helps the backend to choose what it will be searching for in the database.

The example above shows a GET method searching for user with id equals to 3.

### **More than one param**

Now let's think about lists!
Lists are great, right?! so we gonna imagine a scenario where we need to access a list of users that live in a given city and has a given age.

We can pass more than one param to the URL separating them with an "&" sign like this:

_https://www.yourdomain.com/users?city=chicago&age=22_

easy, right?!

### **The problem**

What if we need to tell the backend to send users from two different cities and different ages?

Well, when working with checkbox type filters we have a problem.

So let's check this case out: 

We have these filters in a Vue.js with Vuex application and everytime we click in an option an action is dispatched sending these params in an Object structure to a "filters" array in our state:

```javascript
filters: [
 {"key" = "city", "value"="chicago"},  
 {"key" = "city", "value"="ohio"},
]
```


Now that we have the needed information in the state, we can make our request with Axios after setting up the **base url**:

```javascript

// Action
async GET_USERS() {

// Since we have mixed filters as objects in an array
// we must map them creating a new array with their values
  const cityParams = state.filters.map((filter) =>
      filter.key === 'city' ? filter.value : undefined
    )

  const ageParams = state.filters.map((filter) =>
      filter.key === 'age' ? filter.value : undefined
    )

  const data = await this.$axios.get('/users', {
    params: {
      city: cityParams,
      age: ageParams
    },
  })
}
```

It looks simple, but we still have a problem. If we click in a "22 age" checkbox, we will get the following url: 

_https://yourdomain.com/users?city[]=&age[]=22_

If we click again in another age, for exemple 18:

_https://yourdomain.com/users?city[]=&city[]=&age[]=22&age[]=18_

Maybe the first one will work, if the backend is correctly identifying the keys ending with []. However the second one will break your request returning a 400 status code (bad request).

### **Solving it**

This can be solved by using [QS package](https://www.npmjs.com/package/qs).

Basically it will allow us to stringify the array of params (cityParams and ageParams). 

After download the package using npm or yarn and import it, we can pass it as a third argument in the axios request as it follows:

```javascript
import qs from 'qs';

// Action
async GET_USERS() {

// Since we have mixed filters as objects in an array
// we must map them creating a new array with their values
 const cityParams = state.filters.map((filter) =>
      filter.key === 'city' ? filter.value : undefined
    )

const ageParams = state.filters.map((filter) =>
      filter.key === 'age' ? filter.value : undefined
    )

  const data = await this.$axios.get('/users', {
    params: {
      city: cityParams,
      age: ageParams
    },
    paramsSerializer: (params) => {
      return qs.stringify(params, { arrayFormat: 'repeat' })
    },
  })
}
```

Note that when we map the params, we must return **undefined** if there is no value. 

The values **null** and **'' (empty string)** return the key with empty value by default. Otherwise, **undefined** omit the whole param.

the following argument will repeat key=value for every value we have in the array. 

```javascript
{ arrayFormat: 'repeat' }
```

As result, we have a clean and readable URL (again clicking twice in checkboxes from age filter):

_https://yourdomain.com/users?age=22&age=18_


That was a little bit tricky but incredibly useful, right?!

Hope it helps! :)