It’s just good practice to not return top level arrays as the result for a request. At some point it was a vulnerability like explained here: https://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx/
But, nowadays, I just use it that way because sometimes I add extra properties to the response like this:
{
data: [ ... ],
metadata: { current_page:2, total_pages: 10 }
}
So it’s good to keep separate your data from other attributes you might want in the response.
And regarding the res.data.data
access, I prefer to not have a customized name for the data attribute. Although it sounds good in principle, in the long run is better to have a uniform way to access what you need from the response.
In any case you should be able to instruct your HTTP client to unwrap what you want for you on every request. For example, I have this setup for Axios for interacting with a Phoenix JSON API:
import axios from 'axios'
const baseDataService = axios.create({
baseURL: 'http://localhost:4000/api/',
headers: {
'Accept': 'application/json'/* ,
'Content-Type': 'application/json;charset=UTF-8' */
// Seems like that's the type Axios sends by default
},
withCredentials: true
})
baseDataService.interceptors.response.use(
function (response) {
// Unwrap and return the data property
return response.data
// This is desired unless you have a special need for any of the
// other root properties:
// config, headers, request, status, statusText
},
function (error) {
if (error.response) {
return Promise.reject(error.response)
} else {
return Promise.reject(error)
}
}
)
export default baseDataService
So, on my requests, assuming I’m returning data and metadata (like in the example above) I do something like this:
userService
.all()
.then(res => console.log(res.data, res.metadata))