Reducer 为何必须是纯函数?

前言

本文不讲 react、redux、action、reducer 的具体应用,只是单纯的讲解 reducer 为何必须是纯函数,本文适合有必定 redux 开发经验的同窗。javascript

用过 react 的同窗对 redux 必定不会陌生,咱们知道 redux 能够提供可预测化的状态管理。在一个应用中,全部的 state 都是以一个对象树的形式存在一个单一的 store 中,惟一改变 state 的办法就是触发 action,而 reducer 就是用来编写专门的函数决定每一个 action 如何改变应用的 state 。java

如官网所说,reducer 就是一个纯函数,接受旧的 state 和 action,返回新的 state (previousState, action) => newStatereact

咱们的疑问来了:redux

为何reducer 必须是一个纯函数?
为何必须返回一个新的 state?
返回旧的 state 为何不行?
redux 源码是怎么写的?函数

纯函数写法

咱们首先来看下正常案例,咱们通常会有以下几种写法返回新state:性能

  1. 直接返回一个新对象

  1. 使用 Object.assign()返回一个新对象

  1. 使用 Immutable.js 返回一个新对象

在 Redux store 中保存了 reducer 返回的 这个 state,这个新的 store 树就是应用的下一个 state, 全部订阅 store.subscribe(listener)的监听器都将被调用,监听器里能够调用 store.getState()得到当前 state 此时,咱们就可使用新的 state 来更新 UI setState(newState)设计

什么是纯函数?

这里简单的讲解一下什么是纯函数?3d

  1. 相同的输入永远返回相同的输出
  2. 不修改函数的输入值
  3. 不依赖外部环境状态
  4. 无任何反作用 

为何reducer必须为纯函数?

咱们先来试验下,若是 reducer 不是纯函数会发生什么? 咱们将上面代码reducer改造一下,直接修改 state,而不是返回新的 statecode

改变代码后,咱们发现当咱们触发了 action 之后,页面没有发生任何变化,这是为何呢?cdn

咱们来看下 redux 源码:

经过源代码,咱们发现,var nextStateForKey = reducer(previousStateForKey, action), nextStateForKey就是经过 reducer 执行后返回的结果(state),而后经过hasChanged = hasChanged || nextStateForKey !== previousStateForKey来比较新旧两个对象是否一致,此比较法,比较的是两个对象的存储位置,也就是浅比较法,因此,当咱们 reducer 直接返回旧的 state 对象时,Redux 认为没有任何改变,从而致使页面没有更新。

为何 Redux 会这样设计?

由于比较两个 javascript 对象中全部的属性是否彻底相同,惟一的办法就是深比较,然而,深比较在真实的应用中代码是很是大的,很是耗性能的,须要比较的次数特别多,因此一个有效的解决方案就是作一个规定,当不管发生任何变化时,开发者都要返回一个新的对象,没有变化时,开发者返回就的对象,这也就是 redux 为何要把 reducer 设计成纯函数的缘由。

相关文章
相关标签/搜索