内容简介: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》—— 函数
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Code Reading
Diomidis Spinellis / Addison-Wesley Professional / 2003-06-06 / USD 64.99
This book is a unique and essential reference that focuses upon the reading and comprehension of existing software code. While code reading is an important task faced by the vast majority of students,......一起来看看 《Code Reading》 这本书的介绍吧!