BugHunterUK BugHunterUK - 18 days ago 8
Javascript Question

Why is a Redux reducer called a reducer?

Whilst learning

Redux
I've came across
Reducers
. The documentation states:


The reducer is a pure function that takes the previous state and an action, and returns the next state. (previousState, action) => newState. It's called a reducer because it's the type of function you would pass to Array.prototype.reduce(reducer, ?initialValue) .


MDN describes the
reduce
method as:


The reduce() method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value.


I'm still confused on why the Redux definition of a reducer as it's making no sense. Secondly the MDN description doesn't seem correct either. The
reduce
method isn't always used to reduce to a single value. It can be used in place of
map
and
filter
and is actually faster when used in place of chaining.

Is the MDN description incorrect?

Jumping back to the Redux definition of a reducer, it states:


It's called a reducer because it's the type of function you would pass to Array.prototype.reduce(reducer, ?initialValue)


I'm under the impression that a reducer in Redux is responsible for modifying state. An example reducer:

const count = function(state, action) {
if(action.type == 'INCREMENT') {
return state + 1;
} else if(action.type == 'DECREMENT') {
return state - 1;
} else {
return state;
}
}


... I don't see how this is a function that would be passed to
reduce
. How is that data being reduced to a single value? If this is a function you would pass to
reduce
then
state
would be the callback and
action
would be the initial value.

Thanks for any clear explanations. It's difficult to conceptualize.

Answer

The term "reduce" is actually a functional term used in functional programming. In a language like Haskell, F#, or even JavaScript, we define a transformation that takes a collection (of any size) as input and returns a single value as output.

So (not to be pedantic, but I find this helps me) think of it visually. We have a collection:

[][][][][][][][][][]

...which we want to collapse into a single value.

N

Programming functionally, we would do this with a single function that we could call recursively on each element of the collection. But if you do that, you need to keep track of the intermediate value somewhere, right? Non-pure implementations might keep some kind of "accumulator" or variable outside of the function to keep track of the state, like so:

var accumulator = 0;
var myArray = [1,2,3,4,5];

myArray.reduce(function (each) {
    accumulator += 0;
});

return accumulator;

With pure functions, though, we can't do this, because by definitions, pure functions can't have effects outside of their function scope. Instead or relying on an external variable that encapsulates our "state" between calls, we simply pass the state along in the method.

var myArray = [1,2,3,4,5];

return myArray.reduce(function (accumulator, each) {
    return accumulator + each;
}, 0);

In this case, we call the function a "reducer" because of its method signature - we have each (or current - any name is fine), representing object in the collection, and state (or previous) - which is passed to each iteration of the function, representing the results of the transformation we've already done to the previous elements in the collection.

Note that the MDN documentation is correct; the reduce() function always do return a single value. Now, yes, you can do other stuff with it, if your function that you call has side effects, but you shouldn't. (Essentially, don't use .reduce() as a foreach.) Even if the method you call with reduce has side effects, the return value of reduce itself will be a single value, not a collection.

The cool this about this is that this pattern doesn't just have to apply to arrays or concrete collections, as you've seen in React; this pattern can be applied to streams as well, since they're pure functions.

Hope this helps. For what it's worth, the definition on the Redux site could be improved (as the concept of a reducer isn't just because of Javascript's Array prototype method). You should submit a PR!

Edit: There's a Wikipedia article on the subject. Note that reduce has different names, and in functional languages, it's commonly known as Fold. https://en.wikipedia.org/wiki/Fold_(higher-order_function)#Folds_as_structural_transformations

Comments