DEV Community

Joseph Mawa
Joseph Mawa

Posted on

Passing JSX key attribute to elements in react.

Alt Text
Image by StockSnap from Pixabay

Outline

Introduction

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

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.
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

For example if we have an array of first names.

const firstNames = ["Joseph", "Tom", "Maria", "Chris"];
Enter fullscreen mode Exit fullscreen mode

You can use the map method to create another array comprising of the number of characters in the respective names like:

const charInFirstName = firstNames.map((firstName) => firstName.length);
console.log(charInFirstName); //[6, 3, 5, 5]
Enter fullscreen mode Exit fullscreen mode

Using Array.prototype.map to map array of data in react.

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.

const contributorsList = [
  { name: "Jane Doe", url: "https://www.fakeurl.io" },
  { name: "John Doe", url: "https://www.anotherfakeurl.net" }
];
Enter fullscreen mode Exit fullscreen mode

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

import React from "react";
export default function Contributor(props) {
  return (
    <li>
      <a href={props.url} target="_blank" rel="noopener noreferrer">
          {props.name}
      </a>
    </li>
  );
}
Enter fullscreen mode Exit fullscreen mode

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

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>
  );
}

Enter fullscreen mode Exit fullscreen mode

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:

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.

<div className="wrapper">
      <ul>
        {contributors.map((contributor, index) => (
          <Contributor
            key={index}
            name={contributor.name}
            url={contributor.url}
          />
        ))}
      </ul>
    </div>
Enter fullscreen mode Exit fullscreen mode

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 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:

 <div className="wrapper">
      <ul>
        {contributors.map((contributor, index) => (
          <Contributor
            key={contributor.name + index}
            name={contributor.name}
            url={contributor.url}
          />
        ))}
      </ul>
    </div>
Enter fullscreen mode Exit fullscreen mode

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 keyattribute. 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 or any other platform. Others might find it useful too.

References

Top comments (0)