为什么Redux的状态函数称为reducers?

时间:2015-12-19 22:26:51

标签: javascript redux

这是a part the official Redux documentation

  

它被称为reducer,因为它是你要传递的函数类型   到Array.prototype.reduce(reducer, ?initialValue)

对我来说没有多大意义。有人可以向我解释为什么他们实际上被称为减速器?它们返回默认值(或者它们具有默认参数值)的事实并不能使它们成为减速器恕我直言。

13 个答案:

答案 0 :(得分:60)

  

他们返回默认值(或者他们有默认值)   参数值)不能使它们减速器恕我直言。

Reducers不返回默认值。他们总是返回国家的积累(基于所有先前和当前的行动)。

因此,它们充当状态的 reducer 。每次调用redux reducer时,都会使用操作(state, action)传入状态。然后根据操作将此状态减少(或累积),然后返回下一个状态。这是经典foldreduce函数的一个循环。

由于@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 actionsinitial 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 听起来比 AppluxMutux 酷多了 :)

答案 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函数(由您提供)  数组的每个元素,产生一个输出值。