How to Use JavaScript’s Map Method to Create Lists of Components in React

Prerequisites for understanding this post: You have a basic understanding of the modular nature of React. That is, you understand what React components are, and how we can use them, generally, to separate concerns, as well as use them to render other components.

Working with React can be an absolute pleasure. Thanks to the frontend library’s elegant internal logic, we as developers have the opportunity to break away from the tedious task of writing imperative JavaScript. No longer do we need to traverse the DOM and manipulate our HTML at every step of the way. React allows us to write declarative code, that is, we can tell the frontend client what we want our final result to be, rather than explicitly instruct it how to get there at every step.

One of the most common ways in which you might do this in React is by creating lists (arrays) of JSX elements for the browser to render. To do this, you will likely be making very frequent use of JavaScript’s map method. The map method is called on an array and accepts a callback function as an argument. Map will iterate over the array upon which it was called, and yield each element that it encounters to the callback function, pushing the resulting output in to a new array as it goes. This is a very elegant way to transform some data to suit our needs without mutating the original dataset. For example:

In this example, we map over originalArray, passing each element into an anonymous function that coerces all of the characters to upper case and then pushes the transformed element into a new array (we don’t have to be explicit about the construction of this new array, map is handling all of that for us under the hood). Finally, map’s return value is the newly constructed array; we assign the entire call to map to its own variable (newArray, in the above case) in order to have access to the array that map returns. The important thing to take note of here is that originalArray remains intact. As a result the variables originalArray and newArray point to two distinct array objects.

The above example is obviously a very simply one, but we can leverage this knowledge of map to do extremely powerful things in React. Say, for example, we had an array that consisted of multiple “Person” objects, each with their own distinct set of key value pairs, and that we wanted to create an HTML unordered list using these objects:

All that we had to do in order to achieve this functionality was create two very simple components, a PersonList, and a PersonListItem. In the PersonList component, before rendering any JSX, we call our beloved map method on the “people” array, and transform each entry in the array into its own PersonListItem.

Take a look at line 19 in the above example. Here is where we tell map what we want it to do with each element it encounters (and, thereby, what we want our returned array to consist of). We are essentially saying to map: “construct a PersonListItem component out of each ‘person’ object that you encounter as you iterate over this array.” As a result, our personListItems variable points to an array of four PersonListItem components (four because that is the size of the array that we are calling map on; map will always return an array of the same size as the array upon which it was called). Finally, for the last piece of our PersonList component, we return some JSX. Specifically, we return an HTML unordered list tag, and insert our array of PersonListItem components as the unordered list’s inner content.

Before moving on to the definition of the PersonListItem component, take note of how we are creating what look like HTML attributes (“name={person.name}” & “age={person.age}”) in each PersonListItem that we return from our call to map. These are, in fact, not HTML attributes but, rather, React props (short for properties). Each property we define will get bundled up in to an object called props, which will then be passed as an argument to the PersonListItem definition (line 25). In other words, our call to map creates four PersonListItem components, each with their own props object, and each of those props objects will contain distinct data (the name and age of the person object that we mapped over.)

Finally, let’s look a little more closely at the PersonListItem function itself. As you can see, the component receives ‘props’ as an argument, and then accesses the data that is stored inside of that props object in the returned JSX. It’s that simple! The final resulting HTML of the tandem work that these two components are doing will look something like this:

<ul>
<li>
<p>This person's name is Seth, they are 30 years old</p>
</li>
<li>
<p>This person's name is Sarah, they are 33 years old</p>
</li>
<li>
<p>This person's name is Jim, they are 27 years old</p>
</li>
<li>
<p>This person's name is Mike, they are 42 years old</p>
</li>
</ul>

This may seem like a lot of work and brain power just to render some simple HTML, but imagine that, rather than using a hard-coded array like the one we have above, you are in fact working with an array of objects from a database. There is a very good chance that this array is subject to change. That new objects will be added as your users interact with your app, or that others will be removed or updated. Using this dynamic rendering, we can ensure that our final HTML remains up to date and relevant no matter how many new entries get added to our database (or how many old ones get removed!)

But, alas, we are not quite finished with our implementation. There is one more important piece to implementing lists of JSX elements in React: the “key” prop. If you were clicking around in the above SandBox, you may have stumbled across the console tab and seen the following error:

Warning: Each child in a list should have a unique “key” prop.

First of all, thank React for letting us know what it needs from us! Vanilla JavaScript running in the browser is rarely, if ever, so helpful. Now, what does it mean? Without getting too deep in to the weeds, the “key” prop is used internally by React’s logic in order to keep track of lists of common JSX elements. Each JSX element in a list should have a unique value stored in its key prop. This way, if things get re-ordered, or the size of the list changes, React still has a way of identifying what’s what.

Okay, so how do you go about it? The key prop’s value will always be a string (if you pass it an integer, React will internally coerce it in to a string). The key here (no pun intended) is to pass it something unique. In the above example, we could simple pass in the person object’s name property as the key prop’s value. For example:

const personListItems = people.map((person) => {return <PersonListItem key={person.name} name={person.name} age={person.age} />;});

This would work just fine, until a new person object with the same name value gets added to the array. At this point, the key for those two objects would no longer be unique, and React would complain. The best way to handle the key prop, assuming you are working with an array of database objects, is to simply pass in the objects id as the key prop’s value:

const personListItems = people.map((person) => {return <PersonListItem key={person.id} name={person.name} age={person.age} />;});

Because databases already make sure to assign a unique value for an object’s id, you will never have to worry about this key prop value showing up multiple times.

If, for whatever reason, you are working with an array of objects that do not have database id’s, you have a couple of options:

  1. You can pull in an external library like uuid or nanoid and use the functionality that they provide to generate a random id right in the frontend.
const personListItems = people.map((person, index) => {return <PersonListItem key={index} name={person.name} age={person.age} />;});

As I said, though, option two is considered to be an absolute last resort. You are much better off going with option one. The React documentation advises against using option two, because arrays, being subject to change, won’t always hold the same object at the same index. This could, once again, confuse React’s internal logic and be the root of some un-wanted behavior.

That’s about it! Thanks for reading, if you have any feedback, or would simply like to connect, please feel free to reach out! Until then, happy mapping, and don’t forget to include that “key” prop!

— More resources:

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store