React 是一个前端框架,而 Redux 是一种数据处理解决方案,两者之间没有任何直接联系,可以使用 Redux 中 store.subscribe 函数订阅监听数据改变,然后手动刷新整个应用,但是这样刷新的效率低下,并不能最大化 React 的优点,而 React-Redux 则是专门用于将 React 和 Redux 结合起来,让我们可以使用 state 函数的形式来描述界面,优化应用程序重新渲染。
开始之前需要了解两个概念:容器组件 和 展示组件。
Redux 的 React 绑定库是基于 容器组件 和 展示组件 分离 的开发思想。
两者的异同:
展示组件 | 容器组件 | |
---|---|---|
作用 | 描述如何展现(骨架、样式) | 描述如何运行(数据获取、状态更新) |
直接使用 Redux | 否 | 是 |
数据来源 | props | 监听 Redux state |
数据修改 | 从 props 调用回调函数 | 向 Redux 派发 actions |
调用方式 | 手动 | 通常由 React Redux 生成 |
大部分的组件都应该是 展示型 的,一般需要少数的几个容器组件把它们和 Redux store 连接起来。
技术上讲可以直接使用 store.subscribe() 来编写容器组件。但不建议这么做因为就无法使用 React Redux 带来的性能优化。因此不要手写容器组件,都是使用 React-Redux 的 connect() 方法来生成。
下面来改写上一节中的计算器,使用 React-Redux 来更新计算结果。
state 的结构不变,仍然是一个 int 值表示计算结果;
action 不变,共两个 action,加和减;
reducer 不变,仍然根据 action 的 type 和 num 做相应的加减运算;
step1: 定义展示组件
|
|
和之前的组件定义不同的是,add 和 dec 方法,不再直接使用 store 对象分发 action,而是使用 props 对象的 add 和 dec 方法;另外一个不同点是 span 中显示的计算结果,也是使用 props 对象的 state 属性;props 的 add、dec 方法和 state 属性在后面定义容器组件时会进行定义;
step2: 定义容器组件
|
|
使用 react-redux 提供的 connect 方法定义容器组件,需要提供3个参数
- mapStateToProps : 将 redux 中的 state 转换给展示组件的 props 对象,该对象是一个 function,两个参数 (state, ownProps) 分别表示 redux 中的 state 和 展示组件的 props 对象,该方法需要返回一个 object 对象,对象的所有属性都会被添加到展示组件的 props 对象;
- mapDispatchToProps : 将 redux 中分发 action 的行为转换给展示组件的 props 对象,该对象是一个 function,两个参数 (dispatch, ownProps) 分别表示 redux 中 store.dispatch(action) 函数 和 展示组件的 props 对象,该方法需要返回一个 object 对象,对象的所有属性都会被添加到展示组件的 props 对象;
- connect 将 mapStateToProps 和 mapDispatchToProps 连接到一起,然后将展示组件传给 connect 返回的函数,这个函数返回的组件就是一个容器组件;
mapStateToProps
上面的例子中由于 state 是计算结果值 int,所以直接将 redux 中的 state 赋值给 展示组件的 state 属性;如果是其它 state 结构,则根据需要传入相应的 state 值,比如:
|
|
该代码则将 redux 中 state 对象的 userName 和 userAge 分离开转换给了展示组件。在展示组件中则使用 this.props.userName 和 this.props.userAge 来调用;
mapDispatchToProps
上面的例子中,定义了两个方法 add 和 dec,两个方法分别使用 dispatch 分发加减操作的 action,在展示组件中使用 this.props.add() 和 this.props.dec() 即可调用 store 去分发 action;
step3: 渲染页面
|
|
React-Redux 提供了一个 Provider 组件,把 createStore() 创建的 store 对象传递给该组件,该 Provider 的所有子组件都能获取到 store 对象;
Over
使用 connect 将定义好的 mapStateToProps、mapDispatchToProps 把展示组件和容器组件连接起来,就不需要我们手动去使用 store.subscribe() 来添加监听去处理状态更新了。