动手实现 React-redux(四):mapDispatchToProps
在重构 ThemeSwitch 的时候我们发现,ThemeSwitch 除了需要 store 里面的数据以外,还需要 store 来 dispatch:
...
// dispatch action 去改变颜色
handleSwitchColor (color) {
const { store } = this.context
store.dispatch({
type: 'CHANGE_COLOR',
themeColor: color
})
}
...
目前版本的 connect 是达不到这个效果的,我们需要改进它。
想一下,既然可以通过给 connect 函数传入 mapStateToProps 来告诉它如何获取、整合状态,我们也可以想到,可以给它传入另外一个参数来告诉它我们的组件需要如何触发 dispatch。我们把这个参数叫 mapDispatchToProps:
const mapDispatchToProps = (dispatch) => {
return {
onSwitchColor: (color) => {
dispatch({ type: 'CHANGE_COLOR', themeColor: color })
}
}
}
和 mapStateToProps 一样,它返回一个对象,这个对象内容会同样被 connect 当作是 props 参数传给被包装的组件。不一样的是,这个函数不是接受 state 作为参数,而是 dispatch,你可以在返回的对象内部定义一些函数,这些函数会用到 dispatch 来触发特定的 action。
调整 connect 让它能接受这样的 mapDispatchToProps:
export const connect = (mapStateToProps, mapDispatchToProps) => (WrappedComponent) => {
class Connect extends Component {
static contextTypes = {
store: PropTypes.object
}
constructor () {
super()
this.state = {
allProps: {}
}
}
componentWillMount () {
const { store } = this.context
this._updateProps()
store.subscribe(() => this._updateProps())
}
_updateProps () {
const { store } = this.context
let stateProps = mapStateToProps
? mapStateToProps(store.getState(), this.props)
: {} // 防止 mapStateToProps 没有传入
let dispatchProps = mapDispatchToProps
? mapDispatchToProps(store.dispatch, this.props)
: {} // 防止 mapDispatchToProps 没有传入
this.setState({
allProps: {
...stateProps,
...dispatchProps,
...this.props
}
})
}
render () {
return <WrappedComponent {...this.state.allProps} />
}
}
return Connect
}
在 _updateProps 内部,我们把store.dispatch 作为参数传给 mapDispatchToProps,它会返回一个对象 dispatchProps。接着把 stateProps、dispatchProps、this.props 三者合并到 this.state.allProps 里面去,这三者的内容都会在 render函数内全部传给被包装的组件。
另外,我们稍微调整了一下,在调用 mapStateToProps 和 mapDispatchToProps 之前做判断,让这两个参数都是可以缺省的,这样即使不传这两个参数程序也不会报错。
这时候我们就可以重构 ThemeSwitch,让它摆脱 store.dispatch:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from './react-redux'
class ThemeSwitch extends Component {
static propTypes = {
themeColor: PropTypes.string,
onSwitchColor: PropTypes.func
}
handleSwitchColor (color) {
if (this.props.onSwitchColor) {
this.props.onSwitchColor(color)
}
}
render () {
return (
<div>
<button
style={{ color: this.props.themeColor }}
onClick={this.handleSwitchColor.bind(this, 'red')}>Red</button>
<button
style={{ color: this.props.themeColor }}
onClick={this.handleSwitchColor.bind(this, 'blue')}>Blue</button>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
themeColor: state.themeColor
}
}
const mapDispatchToProps = (dispatch) => {
return {
onSwitchColor: (color) => {
dispatch({ type: 'CHANGE_COLOR', themeColor: color })
}
}
}
ThemeSwitch = connect(mapStateToProps, mapDispatchToProps)(ThemeSwitch)
export default ThemeSwitch
光看 ThemeSwitch 内部,是非常清爽干净的,只依赖外界传进来的 themeColor 和 onSwitchColor。但是 ThemeSwitch 内部并不知道这两个参数其实都是我们去 store里面取的,它是 Dumb 的。这时候这三个组件的重构都已经完成了,代码大大减少、不依赖 context,并且功能和原来一样。
下一节:动手实现 React-redux(五):Provider
上一节:动手实现 React-redux(三):connect 和 mapStateToProps
动手实现 React-redux(四):mapDispatchToProps的更多相关文章
- react+redux教程(四)undo、devtools、router
上节课,我们介绍了一些es6的新语法:react+redux教程(三)reduce().filter().map().some().every()....展开属性 今天我们通过解读redux-undo ...
- react+redux教程(一)connect、applyMiddleware、thunk、webpackHotMiddleware
今天,我们通过解读官方示例代码(counter)的方式来学习react+redux. 例子 这个例子是官方的例子,计数器程序.前两个按钮是加减,第三个是如果当前数字是奇数则加一,第四个按钮是异步加一( ...
- 【原】react+redux实战
摘要:因为最近搞懂了redux的异步操作,所以觉得可以用react+redux来做一个小小的项目了,以此来加深一下印象.切记,是小小的项目,所以项目肯定是比较简单的啦,哈哈. 项目效果图如图所示:(因 ...
- react + redux 完整的项目,同时写一下个人感悟
先附上项目源码地址和原文章地址:https://github.com/bailicangd... 做React需要会什么? react的功能其实很单一,主要负责渲染的功能,现有的框架,比如angula ...
- react + redux 实现幻灯片
写在前面: 这一篇是我 使用scss + react + webpack + es6实现幻灯片 的进阶篇,效果请点我,将会使用上redux的基础用法,因为一开始没有理解好redux的用法,单纯看文档, ...
- React & Redux 的一些基本知识点
一.React.createClass 跟 React.Component 的区别在于后者使用了ES6的语法,用constructor构造器来构造默认的属性和状态. 1. React.createCl ...
- webpack+react+redux+es6开发模式
一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...
- webpack+react+redux+es6
一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...
- React Redux Sever Rendering实战
# React Redux Sever Rendering(Isomorphic JavaScript)  from React Redux (VisibleTodoList)
Learn how to use the that comes with React Redux instead of the hand-rolled implementation from the ...
随机推荐
- Linux搭建lnmp环境
在CentOS 6上使用yum安装lnmp服务,原文链接http://www.qiansw.com/yum-lnmp.html
- maven常用命令总结
搞了多年java 似乎还有些命令 混混沌沌 今儿来总结下 mvn -v 查看版本 mvn -compile 编译当前工程 生成target目录的字节码文件以及报告 mvn -package 将当前工程 ...
- js中的width问题
1.在jQuery中,width()方法用于获得元素宽度: innerWidth()方法用于获得包括内边界(padding)的元素宽度, outerWidth()方法用于获得包括内边界(padding ...
- Linux时间子系统之(一):时间的基本概念【转】
本文转载自:http://www.wowotech.net/timer_subsystem/time_concept.html 本文使用Q & A的方式来和大家以前探讨一下时间的基本概念 一. ...
- string interpolation in sql server
https://sqlserver.dev129.com/2018/01/29/string-interpolation-in-t-sql/ Most programming languages ha ...
- 完美解决pip install scrapy,安装Scrapy错误:Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": http://landinghub.visualstudio.com/visual-cpp-build-tools
1,在Python3.6 安装Scrapy 出现以下报错 2,错误分析 红色报的错误指向的是Twisted 1,Twisted 没安装上 2,Twisted 没安装成功 3,Twisted 版本与Py ...
- hdu 1400 Mondriaan's Dream 解题报告
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1400 题目意思:给出一个h * w的 大 矩形,需要用 1 * 2 的砖块去填充这个大矩形,问填充的方 ...
- php判断某个变量是否存在
sset— 检测变量是否设置,empty — 检查一个变量是否为空(是否存在也检测了,不存在或为空返回true)
- Ntrip通讯协议1.0
Ntrip通讯协议1.0 1 什么是Ntrip? CORS(Continuously Operating Reference Stations)就是网络基准站,通过网络收发GPS差分数据.用户访问CO ...
- nodejs 打造 多人对战游戏服务器(初级入门)
使用socket.set 和 socket.get 在存取玩家信息 百牛信息技术bainiu.ltd整理发布于博客园 socket.get('playerinfo', function (err, p ...