本文是我在学习react技术栈的时候的一些心得,如果发现有纰漏的地方,欢迎在评论区指正,谢谢。
redux的state树的构建过程
我们知道,使用redux的时候,redux把state
集中起来管理,放在一个全局的变量store
中,我们在createStore
的时候,就会建立一一棵state
树,使用store.getState()就可以拿到这棵state树,下面要讲的就是这棵state树是怎样构建起来与怎样维护的。
state树的初始化
state 一开始是为 undefined的,在项目开始加载,调用了createStore()
函数的时候,就会初始化state
。
初始化state的时候有三种可能
1、在createStore()函数里面指定了初始的state
我们先来看下createStore的三个参数
createStore(reducer, [initialState], enhancer)
第二个可选的[initialState]
参数就是我们可以指定的初始的state,我们可以在调用createStore的时候就把初始化的state传进去,那么,state
在初始化的时候就会使用我们传进去的initialState
上述就是在createStore中的源码,我们可以看到,我们传进去的state会被初始化为当前的state。
2、在createStore()
函数里面没有指定初始的state
,不过我们在reducer
的第一个参数state指定了默认值,那么state在初始化的时候就会使用reducer的第一个参数指定的默认值。
// indexList reducer
export default indexList = (state = {
data: [],
loading: true
}, action) => {
// 其他代码
};
在上面的例子我们就为state指定了一个默认的对象,如果传给reducer的state为undefine的话,就会使用state的默认值。注意,这里为state指定默认值我用的是ES6的语法。
3、如果reducer
函数的第一个参数state指定了默认值,同时createStore()
函数里面也传入了[initialState]
,那么就会使用createStore()函数指定的[initialState]
来初始化state。
(这里注意,当使用combineReducers来合成reducer的时候,就算createStore()里面指定了initialState也不会生效,createStore内部初始化state时, 每个reducer的state的默认值会合成一棵state树,作为初始化的state)
state树的更新
分两种情况:
1、没有使用combineReducers()函数
每次调用store.dispatch(action)
的时候,store内部会将两个参数传入到reducer,一个是当前应用的state
,一个是action
,reducer
函数内部会尝试匹配action.type
,如果匹配到,就会返回一个新的state,如果没有匹配到,就把之前传进来的state原封不动返回回去。
注意,这个reducer函数内部如何匹配action.type
和如何返回state
是由我们自己定义的,不过最好是按照上面的规则:如果匹配到,就返回一个新的state,如果没有匹配到,就把之前传进来的state原封不动返回回去。
2、使用combineReducers()函数
首先说一下,根reducer会把所有的子reducer输出的state合并成一棵state树。
如果使用的是combineReducers()
函数把多个reducer联合到一起的话的话,每次调用store.dispatch(action)
,会依次执行每个子reducer,查找匹配的action.type,然后将有改变的state部分更新到state树。
这里说一下,为什么每次都要返回一个新的state,而不是返回旧的state
我们先看下combineReducers.js里面部分的源代码
我们可以看到,新state和旧state只是用浅比较法进行比较,即只比较两个对象在堆中的存储地址,因为如果要进行深比较,即要比较新state和旧state这两个对象里面的每个属性都是否相同,这样的话比较耗费性能。
如果返回的还是旧的state的话,那么state的存储位置并没有改变,所以用浅比较法比较之后,无论state里面的属性有没改变,都会认为state是没变化的。
下面是combineReducers的完整源代码,有兴趣的可以参考学习
combineReducers.js
这里是我基于react+redux构建的实战项目 源代码github地址,欢迎star,有纰漏的地方也欢迎评论指正,谢谢。