Axios and populate - total fail

has anyone else found that populating GET requests in axios is just… awful? I’ve recently fallen back on a simple fetch because i wasn’t getting nested population data from axios. Just wondering if it’s just me or if this is a known issue.

Do you have example code, please?

Axios and Fetch are just different methods of making HTTP Requests with some differences in what they support with fetch being native.

1 Like

I think the problem you’re implying is that there are different standards when it comes to stringifying objects and arrays to a query params string.

If you use the params request config property with your axios requests, chances are that the format that axios produces cannot be read successfully by Strapi, because Strapi uses the qs library for parsing the query params back to an object and expects a different format.

// doesn't out of the box

const restaurantsResponse = await axios.get(`${cmsBaseUrl}/api/restaurants`, {
  params: {
    populate: ['categories', 'city']
  }
});

You have two options to solve this with axios:

  1. You can either decide to not use the params property at all and use qs with every request and add the stringified object to your URL:
const params = qs.stringify({
  populate: ['categories', 'city'],
});

const restaurantsResponse = await axios.get(`${cmsBaseUrl}/api/restaurants?${params}`);
  1. Or you can configure axios’ params serializer on a global level to use qs to stringify the params.
// do this once in your frontend app, eg. in your main.ts or App.ts
axios.interceptors.request.use((axiosRequestConfig) => {
  axiosRequestConfig.paramsSerializer = axiosRequestConfig.paramsSerializer
    ? axiosRequestConfig.paramsSerializer // if you want to still be able to overwrite it on a per-request level
    : qs.stringify;
});

// now every request's params gets stringified with qs so that Strapi can parse it correctly
const restaurantsResponse = await axios.get(`${cmsBaseUrl}/api/restaurants`, {
  params: {
    populate: ['categories', 'city']
  }
});

I personally prefer option 2 because I configure it once and then don’t have to worry about it again. The paramsSerializer can also be configured on a per-request level.

Axios doc:
https://axios-http.com/docs/req_config

qs stringify doc (search for arrayFormat):

2 Likes

agreed as far as what the two do and how they work, what I’m saying is that this url:
/api/orders?populate\[0\]\=items\&populate\[1\]\=items.craft_item

works properly in fetch (and curl) but not in axios, as the craft_item property of each item isn’t populated

I’m a little distracted by other things at the moment, but I really appreciate this response! I did try most of these things to achieve what I’m doing, but in the end i wound up literally encoding the params in the URL, which I’m not really happy with, but at least works in a fetch call

but in the end i wound up literally encoding the params in the URL

You really shouldn’t need to do that :thinking:

/api/orders?populate\[0\]\=items\&populate\[1\]\=items.craft_item

This does look fishy to me will all the escaping and with the dot notation within the param values. The query params should be stringified like this:

const query = qs.stringify({
  populate: {
    items: ['craft_item'],
  },
});
// => 'populate[items][0]=craft_item'

const url = `/api/orders?${query}`
// => `/api/orders?populate[items][0]=craft_item`

same here :laughing:

it was literally the only permutation that i could get to work, and even then in axios it didn’t populate more than one level