点击Increase按钮,可以看到count并没有递增,点击ChangeUser,可以看到username正常更新,此时count才发生变化。为什么呢,因为react-redux先比较state的引用,引用没变化说明dispatch 前后的 state 没有改变,所以此处的counter这个reducer在type未increase的时候并没有返回新的state,而是返回旧的state,那么react-redux即认为状态没有改变,然后再点击ChangeUser的时候返回了新的state副本,引用改变了。这时组件才执行render渲染,那么刚才的count现在才渲染出来。关于组件的render时机可以参考这里
redux核心思想
redux是通用的一套用于项目中统一管理全局状态的框架,这个状态state贯穿整个应用,全局共享,那么就少不了需要使用约定的统一的规范的动作actions来进行state的更新操作reducers。
三大组成
State
全局唯一的共享的state,其实就是一个对象,这个对象里面的属性将来需要在应用中的多个甚至每个页面都要用到并进行更新操作。
Action
当多个页面多个组件都需要在各处进行共享state的操作的时候,如果各自随意修改state,就会变得很混乱,你不知道那个组件在何时何地修改了state,因此,需要一套约定的规范来进行更新state操作,redux提出使用action动作来触发,action相当于一个个钥匙,分发给各个组件,当你需要修改state的时候,只需要dispatch对应的action,这些action收集起来最终去触发对应的reducer执行最终的state更新操作。传给reducer的action始终只能是一个对象,对象中必须要有一个能描述操作的type用于让reducer针对type做对应的处理。
Reducer
reducer就是最终要更新state的函数,参数为传入的state和action,会对不同action.type做出不同操作的函数,在没有任何操作情况下,我们返回初始的initialState。
以上的这个reducer处理increase的时候返回了一个新state,而不是在原来的state上直接修改,为什么要这么做呢?有三点原因,但是让我们先上一大大大大大。。。段示例代码:
./reducers/index
App.js
针对这个例子我们来看一下不修改state的三大理由:
正确的是直接返回一个新的对象{ count: state.count += 1 }
如何正确更新state
比如一个复杂state为如下所示,那么我们可以将其reducer拆分成分别处理count和user的两个,最后通过combineReducers合并。这样在返回副本的时候比较简单,可以直接{count: 2}这种单层的对象。
简单的数据往往一层两层的对象,对于一层对象的改变,也可以使用
但是程序往往是复杂类型的,单层的对象无法满足业务需求的时候,就会出现嵌套很深的对象,这时候Object.assign()就不起作用了,因为Object.assign()只是浅拷贝。。。对于全是可枚举的属性的对象,可以使用如下方法
或者使用lodash的cloneDeep
依然参考这个
每种方案各有优劣,需要视项目情况而定,选择最适合最清晰的方式,才能高效高性能的进行开发!!!boom!!!