Array Iteration Methods
One of the novel things about React is that JSX doesn't include any iteration helpers.
In most templating languages, you have custom syntax like {{#each}}
to help you iterate through a set of data. In frameworks like Angular and Vue, you have directives like v-for
to manage iteration.
React doesn't provide any abstractions here, and so we'll rely on the built-in methods that are part of the JavaScript language, methods like map
and filter
.
If we can become comfortable with these core methods, we'll have a much easier time doing iteration in React. In this section, we'll learn about some of the most common and useful methods.
forEach
We use forEach
when we want to perform some sort of action on every item in an array.
Here's an example:
const pizzaToppings = [ 'cheese', 'avocado', 'halibut', 'custard',];
pizzaToppings.forEach((topping) => { console.log(topping);});
In this example, we're logging the value of each topping, one at a time. Here's what the console output would be:
cheeseavocadohalibutcustard
The forEach
method accepts a function as its argument. This is commonly known as a callback function.
The term “callback function” refers to a function that we pass to another function. In this case, we write an arrow function that looks like this:
(topping) => { console.log(topping);}
We don't call this function ourselves; instead, we pass it as an argument to the forEach
method. The JavaScript engine will call this function for us, supplying the topping
argument as it iterates over the array.
Accessing the index
The callback we pass to forEach
takes a second optional parameter:
const pizzaToppings = [ 'cheese', 'avocado', 'halibut', 'custard',];
pizzaToppings.forEach((topping, index) => { console.log(index, topping);});
The index is the position in the array of the current item, starting from 0. This code would log:
0 cheese1 avocado2 halibut3 custard
A common format
JavaScript gives us several tools for iterating over the items in an array. We could have used a for
loop, and it's arguably much simpler. There are no complicated callback functions! So why should we learn about .forEach
?
Here's the biggest advantage: forEach
is part of a family of array iteration methods. Taken as a whole, this family allows us to do all sorts of amazing things, like finding a particular item in the array, filtering a list, and much more.
All of the methods in this family follow the same basic structure. For example, they all support the optional index parameter we just looked at!
Let's look at another member of this family: the filter
method.
filter
Things start to get really interesting with filter
.
Here's a quick example:
const students = [ { name: 'Aisha', grade: 89 }, { name: 'Bruno', grade: 55 }, { name: 'Carlos', grade: 68 }, { name: 'Dacian', grade: 71 }, { name: 'Esther', grade: 40 },];
const studentsWhoPassed = students.filter(student => { return student.grade >= 60;});
console.log(studentsWhoPassed);/* [ { name: 'Aisha', grade: 89 }, { name: 'Carlos', grade: 68 }, { name: 'Dacian', grade: 71 }, ]*/
In many ways, filter
is very similar to forEach
. It takes a callback function, and that callback function will be called once per item in the array.
Unlike forEach
, however, filter
produces a value. Specifically, it produces a new array which contains a subset of items from the original array.
Typically, our callback function should return a boolean value, either true
or false
. The filter
method calls this function once for every item in the array. If the callback returns true
, this item is included in the new array. Otherwise, it's excluded.
Important to note: The filter
method doesn't modify the original array. This is true for all of the array methods discussed in this lesson.
Here's one more example:
const nums = [5, 12, 15, 31, 40];
const evenNums = nums.filter(num => { return num % 2 === 0;});
console.log(nums); // Hasn't changed: [5, 12, 15, 31, 40]console.log(evenNums); // [12, 40]
map
Finally, we have the map
method. This is the most commonly-used array method, when working with React.
Let's start with an example:
const people = [ { name: 'Aisha', grade: 89 }, { name: 'Bruno', grade: 55 }, { name: 'Carlos', grade: 68 }, { name: 'Dacian', grade: 71 }, { name: 'Esther', grade: 40 },];
const screamedNames = people.map(person => { return person.name.toUpperCase();});
console.log(screamedNames);/* ['AISHA', 'BRUNO', 'CARLOS', 'DACIAN', 'ESTHER']*/
In many ways, map
is quite a lot like forEach
. We give it a callback function, and it iterates over the array, calling the function once for each item in the array.
Here's the big difference, though: map
produces a brand new array, full of transformed values.
The forEach
function will always return undefined
:
const nums = [1, 2, 3];
const result = nums.forEach(num => num + 1);
console.log(result); // undefined
By contrast, map
will "collect" all the values we return from our callback, and put them into a new array:
const nums = [1, 2, 3];
const result = nums.map(num => num + 1);
console.log(result); // [2, 3, 4]
Like filter
, map
doesn't mutate the original array; it produces a brand-new array.
Also, the new array will always have the exact same length as the original array. We can't "skip" certain items by returning false
or not returning anything at all:
const people = [ { id: 'a', name: 'Aisha' }, { id: 'b' }, { id: 'c' }, { id: 'd', name: 'Dacian' }, { id: 'e' },];
const screamedNames = people.map(person => { if (person.name) { return person.name.toUpperCase(); }});
console.log(screamedNames);/* ['AISHA', undefined, undefined, 'DACIAN', undefined]*/
Here's a helpful way to think about map
: it's exactly like forEach
, except it "saves" whatever we return from the callback into a new array.
Accessing the index
Like the other methods we've seen, we can pass a second parameter to access the current item's index:
const people = [ { name: 'Aisha', grade: 89 }, { name: 'Bruno', grade: 55 }, { name: 'Carlos', grade: 68 }, { name: 'Dacian', grade: 71 }, { name: 'Esther', grade: 40 },];
const numberedNames = people.map((person, index) => { return `${index}-${person.name}`;});
console.log(numberedNames);/* ['0-Aisha', '1-Bruno', '2-Carlos', '3-Dacian', '4-Esther']*/
Additional methods
We've seen 3 of the most common methods here, but there are actually several more that follow this same format, including find
(selecting a single item from the array), every
(checking if all items in an array fulfill some condition), and reduce
(combine all items in the array into a single final value).
You can learn more about these methods on MDN.