内容简介: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也完全没有意义了.
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 深入理解 JavaScript 函数
- 【4】JavaScript 基础深入——函数、回调函数、IIFE、理解this
- 深入理解 Java 函数式编程,第 5 部分: 深入解析 Monad
- 深入学习javascript函数式编程
- [译] 深入理解 JavaScript 回调函数
- 重读《深入理解ES6》—— 函数
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
MD5 加密
MD5 加密工具
XML、JSON 在线转换
在线XML、JSON转换工具