Redux
在前面,我们已经介绍了完全使用react
来管理应用数据的麻烦,下面我们将要介绍redux
这种管理应用状态的框架。
1. Redux
redux
的三大基本原则:
- 唯一数据源
- 保持状态只读
- 数据改变只能通过纯函数来完成
下面,我们来具体看一下这个三个基本原则。
唯一数据源
唯一数据源指的是应用的状态数据应该只存储在唯一的一个store
上。这个唯一store
上的状态,是一个树形的对象,每个组件往往只是树形对象上一部分数据。
保持状态只读
保持状态只读,就是说不能去直接修改状态,要修改store
上的状态,必须要通过派发一个action
对象来完成。
数据改变只能通过纯函数来完成
这里所说的纯函数,其实指的就是reducer
。在redux
中,每个reducer
的函数为reducer(state,action)
。第一个参数state为当前的状态,第二个参数action是接收到的action
对象。而reducer
要做的事情就是根据state
和action
的值产生一个新的对象返回。
function reducer(state,action)=>{
const {counterCaption}=action;
switch(action.type){
case ActionTypes.INCREMENT:
return {...state,[counterCaption]:state[counterCaption]+1};
case ActionTypes.DECREMENT:
return {...state,[counterCaption]:state[counterCaption]-1};
default:
return state;
}
}
可以看到,reducer
函数不光接受action
函数,还接受state
作为参数,也就是说,reducer
只负责计算状态,不负责存储状态。
2. 容器组件和傻瓜组件
在redux
框架下,一个react
组件基本上只需要完成以下两个功能:
- 和
redux store
打交道,读取store
的状态,用于初始化组件的状态,同时还要监听store
的状态变化;当store
的状态变化时,需要更新组件状态,从而驱动组件重新渲染。当需要更新store
状态时,就要派发action
对象。 - 根据当前
props
和state
,渲染出用户界面。
如果一个react
组件要包办上面说的两个功能,似乎有点太复杂了。我们可以考虑拆分,拆分为两个组件,分别承担一个任务,然后再把两个组件嵌套起来,完成原本一个组件应该完成的任务。
基于上面的考虑,两个组件是父子组件的关系。其中,承担第一个任务的组件,负责和·Redux Store
打交道的叫做容器组件,也叫做聪明组件;承担第二个任务的组件,负责渲染界面的,叫做展示组件,也叫做傻瓜组件。
react-redux
react-redux
为我们提供了两个主要功能:
connect
:连接容器组件和傻瓜组件;Provider
: 提供包含store
的context
;
connect
export default connect(mapStateToProps,mapDispatchToProps)(Counter)
connect
是react-redux
提供的一个方法,这个方法接收两个参数mapStateToProps
和mapDispatchToProps
,执行结果依然是一个函数,所以才可以在后面加一个圆括号,把connect
函数执行的结果立刻执行,这一次参数是Counter
这个傻瓜组件。
这个connect
函数做了两件事:
把
store
上的状态转换为内层组件的props
==>mapStateToProps
;把内层傻瓜组件中用户动作转化为派送给
store
的动作,也就是把内层傻瓜组件暴露出来的函数类型的prop
关联上dispatch
函数的调用。每个prop
代表的回调函数的主要区别就是dispatch
函数的参数不同。==>mapDispatchToProps
function mapStateToProps(state,ownProps){
return {
value:state[ownProps.caption]
}
}
function mapDispatchToProps(dispatch,ownProps){
return {
onIncrement:()=>{
dispatch(Actions.increment(ownProps.caption))
},
onDecrement:()=>{
dispatch(Actions.decrement(ownProps.caption))
}
}
}