Redux一个为JavaScript应用而生的可预测的状态容器,可以有很多方式使用它,而React应用只是其中一种,所以它的API是高度抽象的,并非只针对React的。
为了使用方便,Redux的作者封装了一个React的专用的库React-Redux,这个库时可选的,是否选用应该权衡一下,因为React-Redux虽然提供了便利,但是需要掌握额外的API,并且要遵守它的组件拆分规范。
UI组件
React-Redux将组件分为两类,UI组件(presentational component)和容器组件(container component),UI组件的特征是:
- 只负责UI呈现,不带业务逻辑
- 没有状态(不使用
this.state
变量) - 所有数据都有参数
this.props
提供 - 不使用Redux的API
简单来说,就是一个只负责展示传入参数的纯组件,它的值(表现行为)完全由参数决定
下面就是一个UI组件的例子:
const title = value => <h1>{value}</h1>
容器组件
容器组件与UI组件的特征相反:
- 负责管理数据和业务逻辑,不负责UI的呈现
- 带有内部状态
- 使用Redux的API
总之,UI组件负责UI的呈现,容器组件负责管理数据和逻辑
如果一个组件既有UI又有业务逻辑,那需要将它拆分为:外面是一个容器组件,里面包含了一个UI组件。前者负责与外部的通信,将数据传递给后者,后者只负责根据参数渲染出视图
React-Redux规定,所有的UI组件都由用户提供,容器组件则是由React-Redux自动生成。也就是说,用户负责视觉层,状态管理则是全部交给React-Redux
connnect()
React-Redux提供了connect
方法,用于从UI组件生成容器组件:
import { connect } from 'react-redux'
const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
上面的TodoList
是一个UI组件,connect
接受了两个参数,输出了一个容器组件VisibleTodoList
新生成的组件中需要处理业务逻辑,必须给出两方面的信息:
- 输入逻辑,将外部的数据(即Store提供的完整的State对象)转换为UI组件的参数(即Prop),这个部分由
connect
的第一个参数mapStateToProps
来完成 - 输出逻辑,由用户在UI组件中的动作来触发Action,并且由UI组件dispatch出去,这个部分由
connect
的第二个参数mapDispatchToProps
完成
Connect接受了一些映射函数,返回了一个想要链接的组件类函数,实际上就是高阶函数(HOC)
mapStateToProps()
mapStateToProps
是一个函数,它的作用是建立一个从外部的State对象到UI组件的Props对象的映射关系
它的返回值是一个对象,里面的每一个键值对就是一个映射:
const mapStateToProps = (state) => {
return {
todos: get