Why is a Redux reducer called a reducer?

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.

Solutions/Answers:

Solution 1:

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 definition, 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 an 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.

Related:  Mongoose: multiple query populate in a single call

Note that the MDN documentation you referenced is correct; the reduce() function always does return a single value. In fact, the reduce method in any language is a higher-order function that takes a “reducer” (a function with the method signature defined above) and returns 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 thing is 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

Solution 2:

The reason why a redux reducer is called a reducer is because you could “reduce” a collection of actions and an initial state (of the store) on which to perform these actions to get the resulting final state.

How? To answer that, let me define a reducer again:

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

And what does a redux reducer do?

The reducer is a pure function that takes the current state and an
action, and returns the next state. Note that the state is accumulated as each action on the collection is applied to change this state.

So given a collection of actions, the reducer is applied on each value of the collection (from left-to-right). The first time, it returns the initial value. Now the reducer is applied again on this initial state and the first action to return the next state. And the next collection item (action) is applied each time on the current state to get the next state until it reaches the end of the array. And then, you get the final state. How cool is that!

Solution 3:

Sorry, but I would disagree with previous answers. I would not support the naming reducer. I’m passionate about FP and immutability. Don’t blame me, read the second part, but I want to state first, why I disagree.

It’s correct that the reducers are the sequence of transformations, but the sequence itself – could be part of another sequence. Imagine it, like links – a part of chain. But the chain itself could be part of longer chain. Each link is the “transition” of the global state. Than, what the theory behind it?

Isn’t it actually the “Finite state machine”? – close, but not. It’s actually the Transition system.

A labelled transition system is a tuple (S, Λ, →) where S is a set of states, Λ is a set of labels and → is a set of labelled transitions

So, S – are set of our states

Λ – is our so-called “actions” (but labels in theory)

… and

reducers “labelled transitions”! I would name it so, if I am creator of this library.

Understanding this theory helped me to implement my library, where I can have low-level transition system as a part of high-level transition system (like chain – still could be part of longer chain) – and still having single global Redux state.

Solution 4:

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

Array.reduce

This is very similiar to what you would pass to Array.reduce as the callback (reducer). The important part being:

callback
  Function to execute on each value in the array, taking four arguments:
    previousValue
      The value previously returned in the last invocation of the callback, or initialValue, if supplied. (See below.)
    currentValue
      The current element being processed in the array.

Where state is the “previousValue” and action is the “currentValue”.

Solution 5:

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.

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

// an array of actions
const actions =
  [ { type: 'INCREMENT' }
  , { type: 'INCREMENT' }
  , { type: 'INCREMENT' }
  , { type: 'INCREMENT' }
  , { type: 'DECREMENT' }
  ]

// initial state
const init = 0
  
console.log(actions.reduce(count, init))
// 3 (final state)
// (INCREMENT 4 times, DECREMENT 1 time)

Solution 6:

These answers are good but I think it’s much simpler than you think. I’ll admit that I had a similar confusion at first. The reduce method on Javascript arrays takes an accumulator and a callback function.

const arr = [1, 2, 3]
const sum = arr.reduce((accumulator, element) => {
  accumulator += element;
  return accumulator;
}); // sum equals 6 now

The reason it’s called a reducer in redux is because it roughly has a similar structure.

const sum = arr.reduce((accumulator, element) => {  // accumulator is the initial state
  accumulator += element; // we do something to modify the initial state
  return accumulator;  // we return that and it becomes the new state
}); 

So every time we run a reducer we take something in, modify it, and return a copy of that same thing. On each iteration we’re pointing to the same thing. Ok, yes, we have to make a copy in redux so as to not directly modify state, but symbolically every time we run it, it’s kind of like the way reduce starts with an initial state in the example above of 1. Then we add 2 to our inital state and return 3. Now we run our ‘reducer’ again with an intial state of 3 and add 3 and we end up with 6.

References