Image by StockSnap from Pixabay
Outline
- Introduction
- Background to
Array.prototype.map
- Using
Array.prototype.map
to map array of data in react - References
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"];
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]
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" }
];
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>
);
}
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>
);
}
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>
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>
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 or any other platform. Others might find it useful too.
Top comments (0)