Passing JSX key attribute to elements in react.
Tags: react, webdev, beginners
Published: 2020-09-10 11:46:03

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/esm33qdrtpv2zw3ti70x.jpg)
Image by <a href="https://pixabay.com/users/StockSnap-894430/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=2557586">StockSnap</a> from <a href="https://pixabay.com/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=2557586">Pixabay</a>

## Outline

* [Introduction](#introduction)
* [Background to `Array.prototype.map`](#background)
* [Using `Array.prototype.map` to map array of data in react](#using)
* [References](#references)


## Introduction <a id = "introduction"> </a>

The focus of this article is on the most common use case of `Array.prototype.map` in react i.e. mapping array of data to array of elements which requires passing JSX key attribute for uniquely identifying each element from its siblings.  

## Background to `Array.prototype.map` <a id = "background"> </a>
If you have used react for some time, most likely you have dynamically created react elements from an array of data using `Array.prototype.map`. If you are not familiar with ES5 `Array` method `map`, you can read about it in the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map). 
In brief:
> The `map()` method creates a new array populated with the results of calling a provided function on every element in the calling array. [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)

For example if we have an array of first names.
```js
const firstNames = ["Joseph", "Tom", "Maria", "Chris"];
``` 
You can use the `map` method to create another array comprising of the number of characters in the respective names like:
```js
const charInFirstName = firstNames.map((firstName) => firstName.length);
console.log(charInFirstName); //[6, 3, 5, 5]
```
## Using `Array.prototype.map` to map array of data in react. <a id = "using"> </a>

In the same way you can map an array of elements using ES5 array method `map`, you can map an array of data to an array of JSX elements in react using `Array.prototype.map`. It is important to point out that though `map` is the easiest, recommended and the most commonly used way of doing  this, you can also achieve the same result by using `for` loop or `forEach` array method.

In the code below, i have created an array of contributors to an open source project.
```js
const contributorsList = [
  { name: "Jane Doe", url: "https://www.fakeurl.io" },
  { name: "John Doe", url: "https://www.anotherfakeurl.net" }
];
```
In the code below, i have created `Contributor` component which returns `li` element with nested `a` tag and it is saved in `Contributor.js` file.
`Contributor.js`
```js
import React from "react";
export default function Contributor(props) {
  return (
    <li>
      <a href={props.url} target="_blank" rel="noopener noreferrer">
          {props.name}
      </a>
    </li>
  );
}
```
Furthermore i have also created `App` component which imports `Contributor`. It then maps an array of contributors to an array of `Contributor` components.
`App.js`
```js
import React, { useState } from "react";
import Contributor from "./Contributor";
const contributorsList = [
  { name: "Jane Doe", url: "https://www.fakeurl.io" },
  { name: "John Doe", url: "https://www.anotherfakeurl.net" }
];
export default function App() {
  const [contributors] = useState(contributorsList);
  return (
    <div className="wrapper">
      <ul>
        {contributors.map((contributor, index) => (
          <Contributor
            name={contributor.name}
            url={contributor.url}
          />
        ))}
      </ul>
    </div>
  );
}

```
The above code will render a list of contributors but with a warning:
> `Warning: Each child in a list should have a unique "key" prop.`

You get the above warning because react expects you to pass a `key` JSX attribute to `Contributor`. The value of `key` should be a string which uniquely identifies each `Contributor` component. According [to the react documentation](https://reactjs.org/docs/lists-and-keys.html):
> A `key` is a special string attribute you need to include when creating lists of elements. 

Keys help react identify which elements have changed, have been deleted or added. It gives the elements in the array a stable identity. If you don't provide explicit keys to the elements in your list, react will default to using the element indices as keys. In fact passing `index` as value of `key` attribute will make the warning disappear because react assumes you know what you are doing.
```js
<div className="wrapper">
      <ul>
        {contributors.map((contributor, index) => (
          <Contributor
            key={index}
            name={contributor.name}
            url={contributor.url}
          />
        ))}
      </ul>
    </div>
```
Though passing index as value of `key` attribute makes the warning disappear, it is not recommended to use element indices as key if the order of items in the array will change. This according to the [react documentation](https://reactjs.org/docs/lists-and-keys.html) is because,
> it will negatively impact performance and may cause issues with component state.

In the example above, i could generate a unique key on the fly by concatenating the index to the name like:
```js
 <div className="wrapper">
      <ul>
        {contributors.map((contributor, index) => (
          <Contributor
            key={contributor.name + index}
            name={contributor.name}
            url={contributor.url}
          />
        ))}
      </ul>
    </div>
```
As a rule of thumb, when creating an array of elements using `map`, the element returned by callback to `map` must have a unique JSX `key`attribute. It is also important to note that `key` is JSX attribute which is not passed as `prop`. If you want to access the value of `key` in your component, then you need to pass it as prop with name other than `key`. Keys used in arrays should be unique among its siblings. It doesn't have to be unique globally.

Though the main focus of this article is use of `Array.prototype.map` to create array of elements from data, you can also use `for` loop or `forEach` array method to do the same.

Thanks for reading this article to the end. If you find something which is technically inaccurate please leave a comment below. If you find it useful, please consider sharing it on [Twitter](http://twitter.com/) or any other platform. Others might find it useful too.
 
## References <a id = "references"> </a>

- [React documentation](https://reactjs.org/docs/lists-and-keys.html)
- [Index as a key is an anti-pattern](https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318)
- [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)