loading...
Cover image for Use this trick to map over single objects in Javascript

Use this trick to map over single objects in Javascript

ari_o profile image Arika O ・2 min read

The title is of course, misleading. We know from Javascript that we can't use the .map() method on non-arrays so what I am talking about? Let's say we make a request to a server and then we convert the json text into the corresponding object. It is of course possible that after the parsing we get back a single object and not an array. If we'll try to iterate over the result, .map() won't work so we'll run into issues. You can see this happening in the code bellow. For simplicity, I didn't fetch any real data, I used some hard-coded one. We have a simple React component that should display the names of the imaginary people we get back from the server. When trying to run the code we'll get an error: Property 'map' does not exist on type Object.

Alt Text

How can we avoid this situation and make sure that we'll be able to map over the result, even if we get a single object after parsing the response? Let's look at the code bellow:

Alt Text

What we did was use the Array.isArray() built-in method to check if what we get back is an array and if it's not, we store the single object into a single element array. Since .map() iterates over single entry arrays, we won't run into an error. You can see the complete code here: https://codesandbox.io/s/sass-jzgxv

P.S: this excludes, of course, the scenario in which fetch returns nothing so then we'll have to check for null responses.
Image source: @divinetechygirl on Pexels

Discussion

pic
Editor guide
Collapse
rallipi profile image
Ralf πŸ’₯πŸ”₯β˜„οΈ

Sorry to say this, but this "trick" is just a workaround for a poorly designed api. If you have to implement such kind of stuff, you should really reconsider reimplementing your api.

If an api endpoint should return a list, it has to return a list even if it only contains one element.

While such workarounds are possible in js, there is no trivial way in doing this in eg C#. And if the same api should get used for a .net project, the c# devs will get mad at you :-)

Collapse
ari_o profile image
Arika O Author

I agree. In an ideal world, this would be true. But I'm talking more about the situation in which we're consuming APIs, not designing them. So the trick is not meant for the API devs but for the consumers who might run into issues because of unpredictable API results.

Collapse
jpantunes profile image
JP Antunes

"Why aren’t objects iterable over properties, by default? The reasoning is as follows. There are two levels at which you can iterate in JavaScript:

The program level: iterating over properties means examining the structure of the program.
The data level: iterating over a data structure means examining the data managed by the program.
Making iteration over properties the default would mean mixing those levels, which would have two disadvantages:

You can’t iterate over the properties of data structures.
Once you iterate over the properties of an object, turning that object into a data structure would break your code. If engines were to implement iterability via a method Object.prototypeSymbol.iterator then there would be an additional caveat: Objects created via Object.create(null) wouldn’t be iterable, because Object.prototype is not in their prototype chain." - exploringjs.com/es6/ch_iteration.h...

Collapse
allnulled profile image
allnulled

Remember you can, in most of the cases, simply do:

[].concat(itemOrItems).forEach(console.log)

This way, you only need to avoid undefined or null values.

Collapse
ari_o profile image
Arika O Author

Why use forEach() instead of map()? ForEach returns undefined so you can't display anything on the page when looping through the array.

Collapse
allnulled profile image
allnulled

Remember that the typical functions in JavaScript functional programming nowadays, are: forEach, filter, map, reduce (the last one is the more powerful of all).

We also have others, like: Object.assign and Object.defineProperty.

I mentioned forEach because it is the simplest, not because it fit in the example.

Thank you.

Thread Thread
ari_o profile image
Arika O Author

Thank you for your input.

Collapse
rehmatfalcon profile image
Kushal Niroula

Wouldn't it be better to just wrap the code to be executed for each item in a method and then call the method directly if it is single item?

Say, something like

if(!Array.isArray(example)) return doSomething(example);
return example.map(doSomething);
Collapse
janpauldahlke profile image
jan paul

hm, i just don't get the advantage here. is it synonym to

 return <p> {example.name} </p>
Collapse
aalireza439 profile image
aalireza439

this useful when your response is usually a list of objects and you're using a map to output it, but when your response is a single item it's not in an array, it's just a single object and using map throw an error.

Collapse
ari_o profile image
Arika O Author

True, but how do you know if the response from the server has one object inside or an array of objects? You'll need to use different rendering methods (use map or not) depending on what you get from the fetch - so you would still need to make a check somewhere.

Collapse
janpauldahlke profile image
jan paul

i thought array in response is no go, because haacked.com/archive/2008/11/20/ana...