map, filter & reduce Functions in React

By Yeo Yong Kiat in ReactJS

15 min read
Let's talk declarative vs imperative coding today. It's something that I've been trying to change about myself when coding in React, because I've found it to be highly efficient, and it'd be great to talk you guys through it. What better way to explain this than through the map, filter & reduce functions in JS?

Is One Better Than The Other?

No actually. Please don't fuel the unnecessary wars between the two paradigms of coding - when to use which is a matter of judgment and the context of your code. As with all things in life, there are trade-offs for each choice of coding style. For example, only in an imperative coding style might you be able to exit a loop early, or perform chunking. But that's for another post - today, we're concerned about explaining what declarative coding is, and the 3 important list functions that I've found useful for React coding.

What Does Declarative & Imperative Mean?

Let's switch topics for a while and think about the English language. Let's just look at two simple statements:

Statement 1: I picked up coding from University.
Statement 2: I went to University, attended CS1101, read from textbooks and worked on real-life projects.

Statement 1 is said to be declarative, because it focuses on what you've done without focussing on the details of how you achieved it. In contrast, Statement 2 is said to be imperative, because it's the reverse - it describes how you did something without really mentioning what you actually achieved.

In terms of the final state, Statement 1 is easier to understand - you know that I managed to pick up coding for sure. And in some sense, declarative programming is easier to understand as well, because it uses pure functions to quickly execute computations without going into granular steps.

What is Imperative Coding?

Imperative coding is coding that directly instructs the computer what to do. Usually this is done in a step-by-step sequence of commands, and very commonly presents itself as some kind of "loop" construct. For example, suppose we want to add the surname "Yeo" to every single member of my household in an imperative manner:

// Some random names
const names = ["John", "Luke", "Jude"];

// Create a new list of full names
var fullNames = [];

// Looping over the names
for (let i = 0; i < names.length; i++) {
fullNames.push(names[i] + " Yeo");
}

console.log(fullNames);
Output:
['John Yeo', 'Luke Yeo', 'Jude Yeo']

So essentially we have just told the computer what to do in very clear and distinct steps:

  • Create an empty new list
  • Flag a name from the old list
  • Add " Yeo" to it to create a new name
  • Append the new name to a new list
  • Do this 3 times

What is Declarative Coding?

In contrast, declarative coding doesn't specify the steps, and leaves it to the computer to figure out the order of operations. For example, suppose we want to achieve the same result as above:

// Some random names
const names = ["John", "Luke", "Jude"];

// Create the new list of full names
const fullNames = names.map( (name) => name + " Yeo")

console.log(fullName);
Output:
['John Yeo', 'Luke Yeo', 'Jude Yeo']

In this code, notice how we've omitted quite a bit of instructions to the computer. We haven't told the computer how many times to perform a loop and we haven't created any empty list beforehand. It might seem pretty trivial in this example, but when your code gets complex, declarative coding makes things a lot more efficient. Tiny things add up in coding, that's the mantra.

map, filter & reduce Functions

At the heart of declarative coding is to work with functions, and to code using expressions rather than sequential commands. I've found three list functions to be extremely useful in React, and it's good to talk about them early.

  • You've already seen the map function in action. Essentially, it takes a list, and maps every single item within the list to an action. It's good for transforming one list into another list:

// Create a list of numbers
someNumbers = [9, 12, 33, 28];
console.log(someNumbers);

// Create a list of those numbers x 2
someNumbersBy2 = someNumbers.map( (number) => number * 2);
console.log(someNumbersBy2);
Output:
[9, 12, 33, 28]
[18, 24, 66, 56]

Technically, the syntax works like this:

// "item" refers to each item in the oldList
newList = oldList.map( someFunction(item) );

// You can define your handler function separately
function someFunction(item) {
    // code that maps each item to something else
};

  • The filter function takes a list and returns a subset of the list based on some condition:

// Create a list of numbers
someNums = [9, 12, 33, 28];
console.log(someNums);

// Get a list of numbers divisible by 3
someNumsDivBy3 = someNums.filter( (num) => num % 3 === 0);
console.log(someNumsDivBy3);
Output:
[9, 12, 33, 28]
[9, 12, 33]

Technically, the syntax works like this:

newList = oldList.filter( someFunction(item) );

function someFunction(item) {
    // some conditional code here
};

  • And then there's the reduce function, which aggregates the items within a list, and returns a single value. In some languages, it's also called the aggregate function. Unlike the previous two functions, it takes two arguments. To illustrate this, we try writing our very own "sum" function for a list of numbers - see if you can figure out how it works:

// Create a list of numbers
someNums = [9, 12, 33, 28];
console.log(someNums);

// Sum the numbers
someNumsTotal = someNums.reduce( (aggregate, currNum) => aggregate + currNum);
console.log(someNumsTotal);
Output:
[9, 12, 33, 28]
82

So yes, a little bit more involved due to the double arguments, but essentially it takes one item of the list, and combines its successor with it to generate a new item. This new item is then combined with the next item in line to generate successive new items until the original list is exhausted. So the syntax reads something like:

newList = oldList.reduce( someFunction(aggregate, curr) );

function someFunction(aggregate, curr) {
    // some code to describe how aggregate & curr
    // ought to be combined
};

So why am I looking into declarative coding? Well, because I've been very lazy and I've been just force-looping every single list that comes to me in my recent projects. It would do me some good to start thinking in a different way, you know, switch things up a bit. :)

In the next post, we return to React and develop our understanding of a React component.

Find more ReactJS stories on my blog. Have a suggestion? Contact me at [email protected].