本文不讲 react、redux、action、reducer 的具体应用,只是单纯的讲解 reducer 为何必须是纯函数,本文适合有必定 redux 开发经验的同窗。javascript
用过 react 的同窗对 redux 必定不会陌生,咱们知道 redux 能够提供可预测化的状态管理。在一个应用中,全部的 state 都是以一个对象树的形式存在一个单一的 store 中,惟一改变 state 的办法就是触发 action,而 reducer 就是用来编写专门的函数决定每一个 action 如何改变应用的 state 。java
如官网所说,reducer 就是一个纯函数,接受旧的 state 和 action,返回新的 state (previousState, action) => newState
react
咱们的疑问来了:redux
为何reducer 必须是一个纯函数?
为何必须返回一个新的 state?
返回旧的 state 为何不行?
redux 源码是怎么写的?函数
咱们首先来看下正常案例,咱们通常会有以下几种写法返回新state:性能
在 Redux store 中保存了 reducer 返回的 这个 state,这个新的 store 树就是应用的下一个 state, 全部订阅 store.subscribe(listener)
的监听器都将被调用,监听器里能够调用 store.getState()
得到当前 state 此时,咱们就可使用新的 state 来更新 UI setState(newState)
设计
这里简单的讲解一下什么是纯函数?3d
咱们先来试验下,若是 reducer 不是纯函数会发生什么? 咱们将上面代码reducer改造一下,直接修改 state,而不是返回新的 statecode
改变代码后,咱们发现当咱们触发了 action 之后,页面没有发生任何变化,这是为何呢?cdn
咱们来看下 redux 源码:
经过源代码,咱们发现,var nextStateForKey = reducer(previousStateForKey, action)
, nextStateForKey就是经过 reducer 执行后返回的结果(state),而后经过hasChanged = hasChanged || nextStateForKey !== previousStateForKey
来比较新旧两个对象是否一致,此比较法,比较的是两个对象的存储位置,也就是浅比较法,因此,当咱们 reducer 直接返回旧的 state 对象时,Redux 认为没有任何改变,从而致使页面没有更新。
由于比较两个 javascript 对象中全部的属性是否彻底相同,惟一的办法就是深比较,然而,深比较在真实的应用中代码是很是大的,很是耗性能的,须要比较的次数特别多,因此一个有效的解决方案就是作一个规定,当不管发生任何变化时,开发者都要返回一个新的对象,没有变化时,开发者返回就的对象,这也就是 redux 为何要把 reducer 设计成纯函数的缘由。