为什么Redux需要reducer成为“纯函数”

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 Redux examples. It currently has four tasks. It shows the fourth one as completed, and is set to show “All” Tasks — both completed and not completed.

下图显示了Redux示例中的一个简单的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 (here’s the source code):

现在,如果您查看用于“ 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:)
  1. Two Quick Ways To Reduce React App’s Size In Production

    两种减少React App生产规模的快速方法

  2. Using Preact Instead Of React

    使用Preact代替React

功能编程 (Functional Programming)
  1. JavaScript Is Turing Complete — Explained

    JavaScript正在完善–解释

  2. Functional Programming In JS — With Practical Examples (Part 1)

    JS中的函数式编程—结合实际示例(第1部分)

  3. Functional Programming In JS — With Practical Examples (Part 2)

    JS中的函数式编程—结合实际示例(第2部分)

  4. Why Redux Need Reducers To Be “Pure Functions”

    为什么Redux需要Reducer成为“纯功能”

ES6 (ES6)
  1. 5 JavaScript “Bad” Parts That Are Fixed In ES6

    ES6中修复的5个JavaScript“不良”部分

  2. Is “Class” In ES6 The New “Bad” Part?

    ES6中的“类”是新的“不良”部分吗?

Web包装 (WebPack)
  1. Webpack — The Confusing Parts

    Webpack —令人困惑的部分

  2. Webpack & Hot Module Replacement [HMR] (under-the-hood)

    Webpack和热模块更换[HMR] ( 后台 )

  3. Webpack’s HMR And React-Hot-Loader — The Missing Manual

    Webpack的HMR和React-Hot-Loader —缺少的手册

Draft.js (Draft.js)
  1. Why Draft.js And Why You Should Contribute

    为什么选择Draft.js,为什么要贡献力量

  2. How Draft.js Represents Rich Text Data

    Draft.js如何表示富文本数据

React And Redux: (React And Redux :)
  1. Step by Step Guide To Building React Redux Apps

    构建React Redux应用程序的逐步指南

  2. A Guide For Building A React Redux CRUD App (3-page app)

    构建React Redux CRUD应用程序指南 (3页应用程序)

  3. Using Middlewares In React Redux Apps

    在React Redux应用程序中使用中间件

  4. Adding A Robust Form Validation To React Redux Apps

    向React Redux应用添加强大的表单验证

  5. Securing React Redux Apps With JWT Tokens

    使用JWT令牌保护React Redux应用程序

  6. Handling Transactional Emails In React Redux Apps

    在React Redux应用程序中处理交易电子邮件

  7. The Anatomy Of A React Redux App

    React Redux应用程序剖析

  8. Why Redux Need Reducers To Be “Pure Functions”

    为什么Redux需要Reducer成为“纯功能”

  9. Two Quick Ways To Reduce React App’s Size In Production

    两种减少React App生产规模的快速方法

销售队伍 (Salesforce)
  1. Developing React Redux Apps In Salesforce’s Visualforce

    在Salesforce的Visualforce中开发React Redux应用程序

翻译自: https://www.freecodecamp.org/news/why-redux-needs-reducers-to-be-pure-functions-d438c58ae468/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值