博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
为什么Redux需要reducer成为“纯函数”
阅读量:2519 次
发布时间:2019-05-11

本文共 5878 字,大约阅读时间需要 19 分钟。

by rajaraodv

通过rajaraodv

为什么Redux需要reducer成为“纯函数” (Why Redux need reducers to be “pure functions”)

You may have heard that Redux depends on “pure functions” from functional programming. Well, what exactly does that mean?

您可能已经听说Redux依赖于函数编程中的“纯函数”。 好吧,这到底是什么意思?

The picture below shows a simple Todo app from . It currently has four tasks. It shows the fourth one as completed, and is set to show “All” Tasks — both completed and not completed.

下图显示了一个简单的Todo应用程序。 目前有四个任务。 它显示第四个已完成,并设置为显示“所有”任务-已完成和未完成。

The right-hand side shows the current state stored in Redux. It’s a simple JavaScript object that captures all the details in one place.

右侧显示了存储在Redux中的当前状态。 这是一个简单JavaScript对象,可将所有细节收集到一个地方。

That’s the beauty of Redux.

这就是Redux的优点。

Now, let’s say you toggled the fourth task to be not-completed. Here’s what the app would look like with a new Redux state:

现在,假设您将第四项任务切换为未完成。 这是带有新Redux状态的应用程序的外观:

Now, if you look at the Reducer for “TOGGLE_TODO” — the one that toggles the status of a Todo item between completed and not completed — it looks like below ():

现在,如果您查看用于“ TOGGLE_TODO”的Reducer —一种在待完成和未完成之间切换待办事项状态的工具,则如下所示( ):

When you toggle a Todo item’s state, this is what happens: the reducer function takes an object that represents the “old” state (i.e. input to a function), then creates a brand new object by copying all the old object’s details into a it (like id and text) and overriding old properties with new ones (completed prop).

当您切换待办事项的状态时,会发生以下情况:reducer函数将一个代表“旧”状态的对象(即输入到函数),然后通过将所有旧对象的详细信息复制到一个it中来创建一个全新的对象。 (例如idtext ),并用新属性覆盖旧属性( 完整的道具)。

纯功能 (Pure functions)

At a fundamental level, any function that doesn’t alter input data and that doesn’t depend on external state (like a database, DOM, or global variable) and consistently provides the same output for the same input is a “pure” function.

从根本上讲,任何不更改输入数据且不依赖于外部状态(例如数据库,DOM或全局变量)并且始终为同一输入提供相同输出的函数都是“纯”函数。

For example, the below add function doesn’t alter “a” or “b”, doesn’t depending on external state, and always returns the same output for the same input.

例如,下面的add函数不会更改“ a”或“ b”,也不依赖于外部状态,并且始终为相同的输入返回相同的输出。

const add = (a, b) => a + b //pure function

Now, if you look at our reducer function, it is a “pure” function as it has the same features.

现在,如果您看一下我们的减速器功能,它是一个“纯”功能,因为它具有相同的功能。

但是为什么减速器应该是“纯”功能? (But why should the reducer be a “pure” function?)

Let’s see what happens if we make our reducer “impure.” Let’s comment out the section where it creates a new object, and instead let’s mutate the state’s completed prop directly.

让我们看看如果使减速器“不纯”会发生什么。 让我们注释掉它创建新对象的部分,而让我们直接更改状态已完成的prop。

case 'TOGGLE_TODO':      if (state.id !== action.id) {        return state;      }
// return {      //   ...state,      //   completed: !state.completed      // }
state.completed = !state.completed;//change original object      return state;
default: ...

Now if we try to toggle the TODO after this change, nothing happens!

现在,如果我们尝试在更改后切换TODO,则什么也不会发生!

Let’s see what’s going on in the Redux’s source.

让我们看看Redux源代码中发生了什么。

Redux takes a given state (object) and passes it to each reducer in a loop. And it expects a brand new object from the reducer if there are any changes. And it also expects to get the old object back if there are no changes.

Redux采用给定的状态(对象),并将其循环传递给每个reducer。 如果有任何更改,它期望减速器提供一个全新的对象。 如果没有更改,它也希望将旧对象取回。

Redux simply checks whether the old object is the same as the new object by comparing the memory locations of the two objects. So if you mutate the old object’s property inside a reducer, the “new state” and the “old state” will both point to the same object. Hence Redux thinks nothing has changed! So this won’t work.

Redux只是通过比较两个对象的内存位置来检查旧对象是否与新对象相同。 因此,如果您在化简器中更改旧对象的属性,则“新状态”和“旧状态”都将指向同一对象。 因此,Redux认为一切都没有改变! 所以这行不通。

But, it still doesn’t answer some key questions like:

但是,它仍然无法回答一些关键问题,例如:

  • Why is Redux designed like this?

    为什么Redux这样设计?
  • Why can’t Redux just make a copy of the old state some place else, then compare object props from reducers?

    为什么Redux不能只在其他地方复制旧状态,然后比较化简器的对象道具?
  • Why is Redux putting this burden on individual developers?

    为什么Redux会给个人开发人员带来负担?

The answer: there is only one way to know if two JavaScript objects have the same properties. To deep-compare them.

答案:只有一种方法可以知道两个JavaScript对象是否具有相同的属性。 进行深度比较。

But this becomes extremely expensive in real-world apps, because of the typically large objects and the number of times they need to be compared.

但这在现实世界的应用程序中变得非常昂贵,因为通常有大对象以及需要比较它们的次数。

So one work around is to have a policy to ask developers to create a new object whenever there is a change, then send it to the framework. And if there are no changes, then send back the old object as it is. In other words, new objects represent new states.

因此,一种解决方法是制定一项策略 ,要求开发人员在发生更改时创建一个对象,然后将其发送到框架。 如果没有更改,则按原样发送回旧对象。 换句话说,新对象代表新状态。

Note that you must clone old states using slice — or a similar mechanism — to copy old values into a new object.

请注意,您必须使用slice或类似机制克隆旧状态,以将旧值复制到新对象中。

Now, with this policy in place, you can compare two objects’ memory location using !== without having to compare each property within each object. And if the two objects are not the same, then you know that the object has changed state (that is, some property somewhere in the JavaScript object has changed). That’s exactly the strategy Redux employs to make things work.

现在,有了此策略,您就可以使用!==比较两个对象的内存位置,而不必比较每个对象中的每个属性。 并且,如果两个对象不相同,则说明该对象的状态已更改(即,JavaScript对象中某个位置的某些属性已更改)。 这正是Redux用来使事情工作的策略。

So that’s why Redux needs for “Reducers” to be pure functions!

这就是为什么Redux需要“ Reducers”成为纯函数!

Thank you for reading! If you liked the post please ? and share it on Twitter!??

感谢您的阅读! 如果您喜欢这个帖子,请? 并在Twitter上分享!

React性能: (React Performance:)

功能编程 (Functional Programming)

ES6 (ES6)

Web包装 (WebPack)

  1. (under-the-hood)

    ( )

Draft.js (Draft.js)

React And Redux: (React And Redux :)

  1. (3-page app)

    (3页应用程序)

销售队伍 (Salesforce)

翻译自:

转载地址:http://mhewd.baihongyu.com/

你可能感兴趣的文章
javascript 学习随笔7
查看>>
<P>标签小细节
查看>>
Linux 命令 - netstat
查看>>
mac 关闭&&显示隐藏文件命令
查看>>
JavaScript 循环绑定之变量污染
查看>>
poj 1038 Bugs Integrated, Inc. 三进制状态压缩 DFS 滚动数组
查看>>
zoj 1654 Place the Rebots 最大独立集转换成二分图最大独立边(最大匹配)
查看>>
Wordpress解析系列之PHP编写hook钩子原理简单实例
查看>>
怎样看待个体经济
查看>>
不明觉厉的数据结构题2
查看>>
面向对象编程思想概览(四)多线程
查看>>
二十三种设计模式及其python实现
查看>>
Math类、Random类、System类、BigInteger类、BigDecimal类、Date类、SimpleDateFormat、Calendar类...
查看>>
【设计模式】 访问者模式
查看>>
关于FFMPEG 中I帧、B帧、P帧、PTS、DTS
查看>>
web前端基础:常用跨域处理
查看>>
request和response的知识
查看>>
bootstrap 表单类
查看>>
20165332第四周学习总结
查看>>
Codeforces Round #200 (Div. 1)D. Water Tree dfs序
查看>>