What is reduce
It's an ES5 method in JavaScript like for..each
and map
which we can use with arrays.
The difference is:
- as the name suggests it reduces the number of values in an array to one.
- we have access to the array's previous value apart from its current value and index.
- we will send the accumulator's start value to the callback function; so when we first start previous value will be the same as the accumulator's start value
A Simple Example of Using reduce
Let's look at a simple example that uses reduce
to count the total of an array.
Imagine you have an array: [98,45,33,47,100,80]
We can write the following code to use the reduce
method to sum up the values in this array:
const scores = [98,45,33,47,100,80];
const totalScores = scores.reduce(
(previousScore, currentScore, index)=>previousScore+currentScore,
0);
console.log(totalScores); //returns 403
What happens in the code is:
- we call the
reduce
method on the arrayscores
. - the method has access to the array's
previous
value,current
value andindex
. *We don't useindex
in this example. - we send zero as the
accumulator
's initial value. - in our example when the method first runs (where
currentScore
is 98),previousScore
assumes the value of zero as sent to the callback function. - the result of
totalScores
is 403. - if we change the initial value of the
accumulator
to 100, the value oftotalScores
then changes to 503.
const scores = [98,45,33,47,100,80];
const totalScores = scores.reduce(
(previousScore, currentScore, index)=>previousScore+currentScore,
100);
console.log(totalScores); //returns 503
Using reduce
in React
Imagine you have the following data structure in the App
component:
const course = {
name: 'Half Stack application development',
parts: [
{
name: 'Fundamentals of React',
exercises: 10,
id: 1
},
{
name: 'Using props to pass data',
exercises: 7,
id: 2
},
{
name: 'State of a component',
exercises: 14,
id: 3
}
]
}
To display the total number of exercises in in the Total
component:
- from
App
sendparts
as a prop toTotal
: - in
Total
, call thereduce
method onparts
. -
parts
contains multiple valuesname
,exercises
andid
. - so we explicitly specify
exercises
as the value we want to use in the calculation.
-
App.js
:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import Total from "./components/Total";
const App = () => {
const course = {
name: "Half Stack application development",
parts: [
{
name: "Fundamentals of React",
exercises: 10,
id: 1
},
{
name: "Using props to pass data",
exercises: 7,
id: 2
},
{
name: "State of a component",
exercises: 14,
id: 3
}
]
};
return (
<div>
<Total parts={course.parts} />
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
-
Total.js
:
import React from "react";
const Total = props => {
const total = props.parts.reduce(
(prevValue, currentValue) => prevValue + currentValue.exercises,
0
);
return <p>Totalzzz: {total}</p>;
};
export default Total;
- Result:
Hope this helps!
Top comments (20)
Okay, that's the how.
The bigger question for me has always been why?
A plain for-loop is almost always both faster and more readable. For one, you can name your total variable, which helps people understand what your code is trying to do.
Even in situations where I'm forced to use an expression (e.g. JSX) I prefer adding an extra function.
The only arguments I've heard in favor of
reduce
is things like "feels more functional", which just never really outweighs priorities like simplicity and speed for me.If there's a case where a
reduce
call doesn't easily refactor into a simpler, faster, more readable procedural version of the same thing, I haven't seen it yet. 🤷♂️Yeah I've wondered about the why too and I finally learnt about
reduce
thanks to a React exercise that required its use. :)But now that I've tried it, I do find the code shorter and simpler to write though I agree it's not very readable.
With the
for-loop
, my code is much longer like the following. Any feedback/suggestion on this?I'd use for-of rather than for-in, since you don't care about the index - introducing it as a variable means the reader has to figure out what's important and filter that out first.
I would also pass
props.parts
to the function, to illustrate the fact that this function doesn't care about anything else - seeing the function signature, a person understands right away what the dependencies of that function are; sometimes that can answer their question without making them scan through the function body to figure out what input the function requires.In general, I'd rather have twice as many lines and have something everyone can immediately read and understand (and modify without breaking it!) without a tutorial - and let a minifier do the minifying.
On the issue of inlining vs functions, I lean heavily towards functions, because glazing over a large render-function, I'd rather see descriptive names like
countTotalExercises
as opposed to an tangle of inline expressions - the reader then knows right away what you're doing and doesn't need to be burdened with how you're doing it, before they need to.And likely this was just an example, but I'd use more descriptive names. 😉
Thank you so much for taking the time to share your valuable feedback. I like how you prioritize readability over other features. Keeping this in mind moving forward.
@yogesnsamy sorry but no, i prefer by far your way of writing tutorials !! it's so refreshing actually !! and it's straight to the point and step by step thing is ... perfect !!! and the fact that i might have to wonder what every line of code does actually helps a lot !! definitely going to follow you and read every tutorial you'll write !
You're too kind. Thank you for making my day!
To me, none of the listed differences is true: the outcome of
reduce()
doesn't have to be a single value - it can be an object, an array of greater/smaller size, or nearly anything; you can access any array item from within other high order methods (likemap()
orforEach()
) at any step, using it's entire set of arguments; you can drag accumulator value inthisArg
of above-mentioned methods just as easy.Thank you for your feedback. Quoting MDN, the documentation does say it returns a
single value
.I'm pretty new to the method, may I know more about your last reference to
thisArg
please?Single value doesn't mean it can't be a collection type I think is the OP's point. For example you can use reduce to easily make a lookup map out of an array:
Yes, thank you for a nice example.
True. Thanks for sharing.
➕ Still a very good article. 🎉🎉🎉Congrats to the author.
Thank you for your kind words. :)
It does help :)
Thank you
Glad to hear! :)
I enjoyed your easy to follow writing style and content. I also appreciate your follow ups to the comments. It shows your readers that you are interested in their comments. Good luck to you!
Appreciate your kind words. Have a good day. :)
why is every freaking tutorial about reduce is about adding damn total number
thank's!!! You helped me a lot, that exercise I am doing on the fullstack site what I was trying to do was render the same component but it didn't work. It did not occur to me to do it from another component. Greetings
There is a bug when calling props.parts,
You have to call props.exercises
Could you see what you're sending as
prop
from App?I'm sending it as the following and just tested that it works:
<Total parts={course.parts} />