深入理解redux之reducer为什么是纯函数

栏目: IOS · Android · 发布时间: 5年前

内容简介:reducer是redux的三个核心概念之一,它指定了应用状态的变化如何响应 actions 并发送到 store,需要由开发人员自己定义,提起reducer,最常想到的一个准则是reducer要是纯函数,那么这其中是什么原因呢,如果不是纯函数的话会导致redux不可用吗?接下来就来一步步分析下这个问题我们定义的reducer负责接收action,并返回一个新的state,但在react组件开发中,我们也仅仅定义了而从未实际调用过reducer,所有reducer作用的原理是什么呢?实际上,组件中我们会手动

reducer是redux的三个核心概念之一,它指定了应用状态的变化如何响应 actions 并发送到 store,需要由开发人员自己定义,提起reducer,最常想到的一个准则是reducer要是纯函数,那么这其中是什么原因呢,如果不是纯函数的话会导致redux不可用吗?接下来就来一步步分析下这个问题

reducer响应actions的原理

我们定义的reducer负责接收action,并返回一个新的state,但在react组件开发中,我们也仅仅定义了而从未实际调用过reducer,所有reducer作用的原理是什么呢?

实际上,组件中我们会手动调用dispatch方法发送action来响应事件,而这里的发送action不止发送action那么简单,还包括了调用reducer,更新状态为reducer的处理结果,触发订阅事件等一系列操作,都是在dispatch的方法内实现的,到这里可以来通过源码的处理流程来了解一些这个过程~

function dispatch(action) {
    ...
    try {
      //将flag置为true,表明处于分发逻辑中
      isDispatching = true 
      
      //currentReducer即为传入的reducer函数,这里会自动调用currentReducer函数,并将返回值赋给currentState
      currentState = currentReducer(currentState, action)
    } finally {
      isDispatching = false
    }
    
    //调用订阅函数
    const listeners = (currentListeners = nextListeners)
    for (let i = 0; i < listeners.length; i++) {
      const listener = listeners[i]
      listener()
    }
    return action
}
复制代码

可以看到,dispatch处理中reducer方法的调用无疑是很关键的一步,经过它的处理之后才生成了新的状态数据   在redux中,保持reducer是一个纯函数非常重要,保证reducer是纯函数要达到以下几点:

  • 不得修改传入的参数
  • 不得调用非纯函数,如Date.now()
  • 不得执行有副作用的操作,如API请求和路由跳转

那么为什么reducer函数要遵守这几点规则呢,如果不遵守的话又会怎么样呢

纯函数条件之一:不得修改传入的参数

function reuderfunc(state = initialState, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return ...
    default:
      return state
  }
}
复制代码

reducer接受的参数由两个,一个是 action ,一个是 state ,其中 action 只是用来传递信息的,完全没有修改的必要,那么 state 呢,既然 reducer 是用来返回一个新的 state 的,在这个过程中直接基于传入的 state 来改,然后再返回,貌似也可以达到效果?   实际上,虽然在reducer处理过程中改变了传入的state,有可能redux还会正常运转,但像时间旅行,录制和回放这类依赖于历史状态的功能则无法实现了,要知道这可是redux当时的设计初衷之一~   特别注意的是,如果改变了传入的参数initState,或该对象底层的任意一个key值,都有可能在应用于react组件时,导致react任为该状态无变化,而不更新组件,因为redux源代码中将oldState和newState(reducer返回的结果)做比较,如果某一级state指定的引用相等,则会导致此结果,这样做是牺牲一点计算性能(生成新对象)来保证页面刷新。

纯函数条件之二:不得调用非纯函数,如 Date.now() 或 Math.random()

redux的核心提供可预测化的状态管理,即无论何时特定的action触发的行为永远保持一致,试想如果reducer中有Date.now()等非纯函数,即使同样的action,那么reducer处理过程中也是有所不同的,不再能保证可预测性

纯函数条件之二:执行有副作用的操作

首先,执行有副作用的操作,如api和路由跳转,因为设置到后台的处理,会带来和上一节同样的问题,同样的action触发后的处理过程可能有所不同(依据后台处理或路由跳转而定),失去了可预测性   其次因为reducer函数的返回值是要作为下一个状态值被返回的,那么试想当reducer中有api调用时,api是会向后台请求数据的异步函数,往往希望后台的请求结果数据会应用于新的state,但是这时候会发现,这个异步函数卸载reducer中没有办法影响到state的更新,因为在异步请求处理完成时,reducer函数已经被返回(函数的返回是同步的),所以说在redcuer中调用api也完全没有意义了.


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

.net之美

.net之美

张子阳 / 机械工业出版社 / 2014-1-1 / 79

本书是.NET 程序员进阶修炼的必读之作,由拥有多年开发经验的资深.NET 技术专家对C# 和.NET 中实用的、关键的和难以理解的知识点进行了深入解析,旨在帮助读者在尽可能短的时间内以 尽可能低的学习成本去掌握那些最应该被掌握的知识。书中的每个知识点都辅之以精心设计的案例,易 于理解,实践性强。 全书共17 章,分为两个部分:第一部分(1~5 章)主要讲解了C# 语言中的一些关键知识点,如......一起来看看 《.net之美》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具