动手实现 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 ...