背景

最近在看antd源码,也在自学一些typescript的语法以及使用,然后准备带在学校的师弟做一个音乐播放器作为typescript的练习踩踩坑;

然后竟然没想到在项目刚开始就深陷大坑--搭建react-redux项目流程,一下内容就是记录我是怎样从这个深坑中爬出来的过程。

开始?根本开始不起来

从项目创建之后就掉坑里了。。。

创建项目

创建项目的流程很简单,可有参考我之前写的这篇文章

从mapStateToProps&mapDispatchToProps开始爬坑

刚开始还不是很熟悉typescript,所以我最开始的reducer, action, constant,文件都是以.js结尾,只有组件的代码是以.tsx结尾的,然后就开始按照流程,将store中的state进行mapStateToProps以及actions进行mapDispatchToProps,谁想到这竟然是噩梦的开始,最开始我是这样写的代码:

  import { bindActionCreators } from 'redux';function mapStateToProps(state: {}) {return {player: state.PlayerStore,};}function mapDispatchToProps(dispatch: Function) {return {playerActions: bindActionCreators(actions, dispatch)};}复制代码

然后就开始报错了。。。

1

几经折腾之后我又将代码改成了这样,才得以过关

  import { bindActionCreators, Dispatch } from 'redux';function mapStateToProps(state: { PlayerStore: object }) {return {player: state.PlayerStore,};}function mapDispatchToProps(dispatch: Dispatch<{}>) {return {playerActions: bindActionCreators<{}>(actions, dispatch)};}复制代码

爬坑react组件断言类型

  interface PlayerPropsClass {player: PlayerStateTypes;playerActions: actions.PlayerActionsTypes;}class Player extends React.Component<PlayerPropsClass, {}> {constructor(props: object) {super(props as PlayerPropsClass);this.state = {};}addOne = (num: number) => this.props.playerActions.count(num);subtractOne = (num: number) => this.props.playerActions.subtract(num);render() {const { countNumber } = this.props.player.toJS();return (<div className="player"><span>{countNumber}</span><button onClick={() => this.addOne(countNumber as number)}>点击+1</button><button onClick={() => this.subtractOne(countNumber as number)}>点击-1</button></div>);}}export default connect(mapStateToProps, mapDispatchToProps)(Player as any);复制代码

这里的(Player as any)报错提示

  [tslint] Type declaration of 'any' loses type-safety. Consider replacing it with a more precise type, the empty type ('{}'), or suppress this occurrence. (no-any)复制代码

然后我改成

  export default connect(mapStateToProps, mapDispatchToProps)(Player as {});复制代码

仍然报错

  [ts]类型“{}”的参数不能赋给类型“ComponentType<{ player: object; } & { playerActions: {}; }>”的参数。不能将类型“{}”分配给类型“StatelessComponent<{ player: object; } & { playerActions: {}; }>”。类型“{}”提供的内容与签名“(props: { player: object; } & { playerActions: {}; } & { children?: ReactNode; }, context?: any): ReactElement<any> | null”不匹配。复制代码

哇心态爆炸,都不知道怎么写这个断言。。。然后我想起了antd的一个例子,写的是React.ReactElement,然后偶然间在网上找到了说的是在node_modules中有一个@type文件夹就是typescript对于node包中的相应的类型匹配,于是我就按照这个路径node_modules/@types/react/index.d.ts,终于找到了React.ComponentType<T>,这个文件里面还有很多的类型,想要了解的可以自己去看看

  export default connect(mapStateToProps, mapDispatchToProps)(Player as React.ComponentType<PlayerPropsClass>);复制代码

爬坑action和reducer

有了以上的经验,再加上在这里看了一些代码,我决定把actions和reducer也改为ts结尾的文件;

  • src/reducers/index.ts

      import { combineReducers, createStore } from 'redux';import PlayerStore from '../containers/Player/reducer';// 这个是用来使用到mapStateToProps函数的地方给state进行类型检测的export interface AppStoreType {PlayerStore: object;}const rootReducer = combineReducers({PlayerStore,});export default () => {return createStore(rootReducer);};复制代码
  • containers/Demo/reducer.ts

      import * as PlayerTypes from './constant';import { fromJS } from 'immutable';// 由于使用到immutable,state上面就会使用到immutable的函数,所以需要将其也做成类型检测import { ImmutableFuncType } from '../../constant';interface ActionType {type: string;countNumber?: number;}interface StoreType {countNumber: number;}// 把当前容器的state组,然后抛出提供使用export type PlayerStateTypes = StoreType & ImmutableFuncType;const PlayerStore: PlayerStateTypes = fromJS({countNumber: 0,});export default (state = PlayerStore, action: ActionType) => {switch (action.type) {case PlayerTypes.COUNT:return state.update('countNumber', () => fromJS(action.countNumber));default:return state;}};复制代码
  • containers/Demo/action.ts

      import * as PlayerTypes from './constant';export const count = (num: number) => ({type: PlayerTypes.COUNT,countNumber: num + 1,});export const subtract = (num: number) => ({type: PlayerTypes.COUNT,countNumber: num - 1,});// 抛出actions函数的类型以供mapDispatchToProps使用export interface PlayerActionsTypes {count: Function;subtract: Function;}复制代码
  • containers/Demo/index.tsx

      import * as React from 'react';import './style.css';import { connect } from 'react-redux';import { bindActionCreators, Dispatch } from 'redux';import * as actions from './action';import { PlayerStateTypes } from './reducer';import { AppStoreType } from '../../reducers';interface PlayerPropsClass {player: PlayerStateTypes;playerActions: actions.PlayerActionsTypes;}function mapStateToProps(state: AppStoreType) {return {player: state.PlayerStore,};}function mapDispatchToProps(dispatch: Dispatch<{}>) {return {playerActions: bindActionCreators<{}>(actions, dispatch)};}class Player extends React.Component<PlayerPropsClass, {}> {constructor(props: object) {super(props as PlayerPropsClass);this.state = {};}addOne = (num: number) => this.props.playerActions.count(num);subtractOne = (num: number) => this.props.playerActions.subtract(num);render() {const { countNumber } = this.props.player.toJS();return (<div className="player"><span>{countNumber}</span><button onClick={() => this.addOne(countNumber as number)}>点击+1</button><button onClick={() => this.subtractOne(countNumber as number)}>点击-1</button></div>);}}export default connect(mapStateToProps, mapDispatchToProps)(Player as React.ComponentType<PlayerPropsClass>);复制代码

结尾

通过这个小练习还真的是感受到了typescript的好处,那就是在编译时就报错,而且能够知道报错原因,不需要在编译完成以后再去进行错误点的查找,确实节省了很多时间,尤其是对于JavaScript代码的undefined和null的处理很友好。。总之,感觉写起来很流畅啊。啊哈哈哈哈~~~

使用 Typescript 踩 react-redux 的坑相关推荐

  1. 用 TypeScript 写 React Redux - 完全指南

    "这个指南是一个最新的摘要,记录了关于如何用TypeScript 以函数式风格使用React(以及相关生态)最重要的模式和示例.它会使你的代码在从具体实现中进行类型推导时绝对是类型安全的,这 ...

  2. 基于 react, redux 最佳实践构建的 2048

    前段时间 React license 的问题闹的沸沸扬扬,搞得 React 社区人心惶惶,好在最终 React 团队听取了社区意见把 license 换成了 MIT.不管 React license ...

  3. 最近在搞react redux react-router等,

    React: 我查了英文官网,中文官网,转了社区,对我这样的菜鸟而言,看是看懂了,主要是怎么把项目架起来... 先来说下学习心得: 鄙人拙见:看了大众点评的实战项目,之前也看了小码哥的react na ...

  4. 如何使用webpack+react+redux从头搭建Todolist应用

    webpack环境配置 应用整体框架设计 代码实现 Container Components Actions Reducers indexjs 测试 总结 一言不和先上demo: https://ms ...

  5. react实战项目_React实战之React+Redux实现一个天气预报小项目

    引言 经过一段时间的React学习,React和Vue的开发确实有很大的不同,但是都是MVVM框架,因此上手没有很大的难度,这次用React+Redux开发一个天气预报小项目.源码地址:https:/ ...

  6. 使用Typescript和React的最佳实践

    by Christopher Diggins 克里斯托弗·迪金斯(Christopher Diggins) 使用Typescript和React的最佳实践 (Best practices for us ...

  7. fs react 使用 保存文件_入门TypeScript编写React

    使用 create-react-app 开启 TypeScript Create React App 是一个官方支持的创建 React 单页应用程序的CLI,它提供了一个零配置的现代构建设置.当你使用 ...

  8. webpack+react+redux+es6开发模式---续

    一.前言 之前介绍了webpack+react+redux+es6开发模式 ,这个项目对于一个独立的功能节点来说是没有问题的.假如伴随着源源不断的需求,前段项目会涌现出更多的功能节点,需要独立部署运行 ...

  9. 学习用TypeScript写React组件

    为了折腾, 简单的学习了下TypeScript, 感觉确实不错. 也为了不断学习, 避免落伍, 所以就折腾不断. 前段时间用ES6,antd+dva写了一些demo, 发现antd使用TypeScri ...

  10. 使用react+redux+react-redux+react-router+axios+scss技术栈从0到1开发一个applist应用

    先看效果图 github地址 github仓库 在线访问 初始化项目 #创建项目 create-react-app applist #如果没有安装create-react-app的话,先安装 npm ...

最新文章

  1. python:实现简单购物车增加商品、删除商品的功能
  2. Educational Codeforces Round 106 (Rated for Div. 2) C. Minimum Grid Path 奇偶 + 思维
  3. java nio教程_Java NIO教程
  4. 8597 石子划分问题 dpdp,只考虑第一次即可
  5. 西电网络攻防大赛--渗透测试第二题
  6. 竖流式沉淀池集水槽设计计算_竖流式沉淀池的设计
  7. Skip-Thought Vector —— 跳跃思维句表示
  8. 方法 手写promise_手写Promise类
  9. redis 经纬度_Redis 中的 GEO(地理信息)类型
  10. IBM押宝比特币 开始测试交易软件块链
  11. 非参贝叶斯(Bayesian Non-parameter)初步
  12. Hadoop学习(2)Eclipse配置Hadoop开发环境+HDFS Java API测试+Bug解决记录
  13. 雨滴桌面显示html,如何用雨滴桌面设置美观的桌面天气插件
  14. 计算机网络换算方法,网络带宽换算
  15. matlab tif dpi,轻松解决杂志要求的300dpi分辨率、TIFF格式图片
  16. nagios使用nsca实现被动监控
  17. 十一、MySQL触发器
  18. python获取网页内容 不打开_网页抓取python不返回任何内容
  19. 下一个可扩展性障碍:大型多玩家手机AR
  20. BTG遭遇51%攻击,幕后黑手竟是他!

热门文章

  1. [转] Android应用如何反馈Crash报告
  2. RSync服务器配置
  3. Windows Live SkyDrive, Windows Live Sync 和 Live Mesh
  4. 2018.6.5今天跟着视频做了一个提交Todolist
  5. 单主机Docker容器VLAN划分
  6. iOS 切换首页-更改tabbar的容器控制器
  7. leetCode 204. Count Primes 哈希 求素数
  8. Stooge排序与Bogo排序算法
  9. Python基础学习:svn导出差异文件脚本
  10. DFS建立准备之基于windows 2008 R2的第二台域控建立