这是a part the official Redux documentation:
它被称为reducer,因为它是你要传递的函数类型 到
Array.prototype.reduce(reducer, ?initialValue)
对我来说没有多大意义。有人可以向我解释为什么他们实际上被称为减速器?它们返回默认值(或者它们具有默认参数值)的事实并不能使它们成为减速器恕我直言。
答案 0 :(得分:60)
他们返回默认值(或者他们有默认值) 参数值)不能使它们减速器恕我直言。
Reducers不只返回默认值。他们总是返回国家的积累(基于所有先前和当前的行动)。
因此,它们充当状态的 reducer 。每次调用redux reducer时,都会使用操作(state, action)
传入状态。然后根据操作将此状态减少(或累积),然后返回下一个状态。这是经典fold
或reduce
函数的一个循环。
由于@azium总结为state -> action -> state
。
答案 1 :(得分:20)
如果您认为应用中的一系列操作类似于列表,或者更像是流,则可能更有意义。
采取这个人为的例子:
['apple', 'banana', 'cherry'].reduce((acc, item) => acc + item.length, 0)
第一个参数是(Int, String) => Int
形式的函数。除了初始值,您还可以传递reduce
所谓的“减速器函数”,并获得处理该系列项目的结果。您可能会说,reducer函数描述了每个连续的单个项目所做的更改结果。换句话说,reducer函数获取先前的输出和下一个值,并计算下一个输出。
这类似于Redux reducer的作用:它采用先前的状态和当前动作,并计算下一个状态。
在真正的函数式编程风格中,您可以在概念上擦除应用于参数和结果的含义,并只关注输入和输出的“形状”。
在实践中,Redux Reducer通常是正交的,在某种意义上,对于给定的操作,它们并不都对相同的属性进行更改,这使得分割它们的职责和使用{{1}汇总输出变得容易。 }。
答案 2 :(得分:12)
如前所述,该名称与函数式编程中的reducer概念有关。您可能还会发现Reducer的Merriam-Webster字典定义很有用:
1a上。汇总或导致汇合:巩固(将所有问题减少到一个)
reducer将操作合并到表示应用程序状态的单个对象中。
答案 3 :(得分:6)
将redux reducer称为
reducer
的原因是因为您可以“减少”执行这些操作的collection of actions
和initial state
(商店)获得结果final state
的操作。
如何?要回答这个问题,让我再次定义一个减速器:
reduce()方法对
function (reducer)
和accumulator
应用function
数组的值(从左到右)将其减少为单个 值。
还原剂有什么作用?
reducer是一个纯
accumulated
,它采用当前状态和 动作,并返回下一个状态。请注意,状态为collection of actions
,因为应用集合上的每个操作都会更改此状态。
因此,给定initial value
,reducer将应用于集合的每个值(从左到右)。第一次,它返回current state
。现在,reducer再次应用于此初始状态,并且第一个操作将返回下一个状态。并且每次在next state
上应用下一个集合项(操作)以获取the final state
,直到它到达数组的末尾。然后,你得到ControllerBlock and ControllerAction
。这有多酷!
答案 4 :(得分:3)
作者认为state是reduce函数的累加器。例如:
Final State = [Action1, Action2, ..., ActionN].reduce(reducer, Initial State);
reduce函数来自Functional Programming,名称“reducer”也来自FP。
我不喜欢在这里使用这个名字。因为在动作之后我没有看到世界是单一的价值结果。这里的州是一个对象。例如:
['eat', 'sleep'] === [addTodo('eat'), addTodo('sleep')].reduce(reducer, []);
这个 Reducer 完全没有减少任何东西。而且我不在乎它是否减少任何东西。将其命名为传感器会更有意义。
答案 5 :(得分:3)
我们知道Reducers来自哪里(函数式编程),以及为什么它们可能被认为是在减少工作(将n个输入项减少到单个返回值 - 这正是所支持的正常函数所做的)。 但是:名字只是一个名字,就像玫瑰是玫瑰的名字。不要想太多。 Redux程序员是IT人员,他们被锁定在他们的环境中,并且它是有道理的。我们其他人必须接受发明者的权利,将蓝狗称为黄猫;-)
答案 6 :(得分:1)
我还不太清楚Redux reducer如何直接映射到您与reduce
一起使用的函数,因此,这里有一些示例来说明它们如何匹配。
首先是MDN Array.reduce文档中的标准化简函数(在MDN中称为“累加器”),然后是Dan Abramov的Counter.js
的简化示例,在其'You might not need Redux' blog post的末尾。
sum
向累加器添加值reducer
向累加器添加/减去一个值。在两种情况下,“状态”都是整数。
您正在将操作“累积”到状态中。这也是修改任何JavaScript对象的不变方法。
const sum = function(acc, val) {
return acc + val;
};
const reducer = function(state, action) {
switch (action) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
};
console.log('sum', [1, -1, 1].reduce(sum, 0));
console.log('reduce', ['INCREMENT', 'DECREMENT', 'INCREMENT'].reduce(reducer, 0));
console.log('sum', [1, 1, 1].reduce(sum, 0));
console.log('reduce', ['INCREMENT', 'INCREMENT', 'INCREMENT'].reduce(reducer, 0));
答案 7 :(得分:1)
不应将它们称为减少意味着减少的减少,这些功能通常会产生更多。然后返回
答案 8 :(得分:1)
可以说,这是一个糟糕的命名选择。 (主观评论,无冒犯,我同意命名很难,你不能同时让每个人都开心。)
我知道人们,仅仅因为这个命名,很难适应 redux。当我告诉他们时,这是一个简单的“状态改变器”,然后一切都神奇地变好了。因此,我们没有使用 reducer
这个词,而是开始使用 stateChanger
作为 reducer 的函数名称。
琐事:
从计算机科学的角度来看,归约是使用一个问题的算法来解决另一个问题(解决一个问题也可以解决另一个问题)。例如 SAT 类问题减少到 3SAT 类。这意味着所有 SAT 问题都可以由 3SAT 类问题的求解器解决。 (为谁敲响了钟声 - 或者只是感兴趣 - 你可以参考最伟大的活着的头脑 Scott Aaranson's lecture on the subject)正如你所看到的,这里的 reduce 与 redux 的 reducers 无关。
我们的方法:
另一方面,redux 的 play area 更像是“状态机”。所以reducer实际上是一个状态改变函数。这就是为什么我们在公司中使用 stateChanger
命名以避免每次都考虑函数在做什么。 (是的,几毫秒是我们试图避免的,因为它有时会让我们烦恼,因为我们失去了对主要问题的关注。而且由于 redux 是表示层数据的核心,我们经常出现相同的位置并避免即使是毫秒对我们来说也很有价值。)
答案 9 :(得分:1)
调用 Redux reducers reducers 在语义上是不正确的并且没有多大意义。 这就是作者困惑的原因。
reducer 是一个函数,它将一组值减少为单个值。
我们也可以说它折叠值 - 因此是函数式编程中的经典 fold()
fn。
由于 Redux reducer 不折叠一组值,而是将一个动作应用于一个状态并且总是返回相同的形状(State -> Action -> State
) - 它应该被称为 applicator 或 applier。
但是,由于我们必须始终返回相同的状态形状,而不仅仅是完全不相关的 - 我们将 Redux 状态应用程序称为 changers、< em>transformers 或 mutators。
而且,使用诸如'mutate the state' 和'state mutator' 之类的术语确实已经司空见惯。
但 Redux 听起来比 Applux 或 Mutux 酷多了 :)
答案 10 :(得分:0)
其他答案很好地说明了为什么如此命名,但让我们尝试命名更多内容...
const origState = 0;
const actionOperators = {
increment: (origState) => origState++,
decrement: (origState) => origState--,
};
const anOperator = (aState, anAction) => actionOperators[anAction](aState);
const actions = ['increment', 'decrement', 'increment'];
const finalState = actions.reduce(anOperator, origState);
首先,可以将reduce
称为use anOperator with every action name and accumulated state, starting with origState
。在Smalltalk中,它称为actions inject: origState into: anOperator
。
但是您实际上向操作员注入了什么? origState和操作名称。因此,即使在Smalltalk中,方法名称也不是很清楚。
actionOperators[increment]
是一个Reducer,但我宁愿将其称为actionOperator,因为它是为每个操作实现的。状态只是一个参数(另一个是返回值)。
在Google搜索结果的顶部,Reducer是一个更好的词。它也与Redux类似。
答案 11 :(得分:0)
从现在开始,我们将其称为 Deducer 。它根据先前的状态和传入的动作推导新的状态。
答案 12 :(得分:0)
在下面的代码中,您只需要将累加器视为动作,将currentValue视为redux上下文中的状态。通过此示例,您将了解为什么他们也将其命名为减速器。
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// Main operation is 1 + 2 + 3 + 4 = 10
// but think of it as a stack like this:
// | 2 | | 3 | | 4 |
// |_1_| |_3_| |_6_| | 10 | => the 10 is in result
console.log(array1.reduce(reducer));
// expected output: 10
reduce()方法在以下位置执行reducer函数(由您提供) 数组的每个元素,产生一个输出值。