在React中使用Typescript

在React中使用Typescript

最近学习的技术发现TS越来越多,于是自己尝试做了几个Demo实战,发现TS上手不是很难,但是一旦出现错误很难百度到对应的文档,而且在react中也不会使用ts来编写

跟着这个文章走,内容可能会很长,一步一步去写,保证你的React项目可以使用TS来编写

本人写的一个 TS+Hooks简易版实战

1. 创建一个React的TS项目

react的脚手架create-react-app默认支持TS的文件

npx create-react-app ts-demo --typescript

创建完会发现根目录下面多了一个tsconfig.json文件

2. 使用Typescript编写一个类组件

  • 类组件可以接受props,并且每个类组件都有state数据,所以他需要有两个数据类型规范

子组件

import React from 'react'

interface IState {
	title:string
}

interface Iprops {
    count: number
}

class Child extends React.PureComponent<Iprops, IState> {
	state = {
    	title: 'ts'
	}
	render(){
        return <div>
            {this.state.title}
        	{this.props.count}
        </div>
    }
}

export default Child

父组件

import React from 'react'
import Child from './child'

interface IState {
	count: number
}

interface Iprops {}

class Parents extends React.PureComponent<Iprops, IState> {
	state = {
		count: 0
	}
	render(){
        return <Child count={count} />
    }
}

3.使用Typescript编写一个函数组件

  • 由于函数组件的state使用的是钩子一个一个勾进来的,所以他就需要一个泛型

子组件

import React from 'react'

interface Iprops {
	count: number
}

const Parent:React.FC<Iprops> = props => {
    const { count } = props;
    return <div>{count}</div>
}

父组件

import React, { useState } from 'react'
import Child from './child'

interface Iprops {}

const Child:React.FC<Iprops> = () => {
    const [count,setCount] = useState<number>(0)
    return <div>
        	<button onClick={()=>setCount(count+1)}>+1</button>
        	<Child count={count} />
        </div>
}

export default Child

4.在TS中使用react-router

个人查看对于react-router的影响较少

  • 当我们使用Route组件或者使用withRouter的时候,都会给组件绑定history,location,match三个属性,但是props上面默认是没有的,需要引入router对应的文件

初版

import React from 'react'
import { withRouter } from 'react-router-dom'

interface Iprops{}

const App:React.FC<Iprops> = props => {
    console.log(props.pathname) // 能打印出来结果,不过现在的props是any类型,并且没有提示
    return <div></div>
}

export default withRouter(App)

使用TS

import React from 'react'
import { withRouter,RouteComponentProps } from 'react-router-dom'

interface Iprops extends RouteComponentProps{}

const App:React.FC<Iprops> = props => {
    console.log(props.pathname) // 有提示,并且props有他的类型规定
    return <div></div>
}

export default withRouter(App)

5.在TS中使用Redux

个人认为使用redux算是最麻烦的一步了

  • 这里面我选择使用 react-redux,redux-thunk,redux

reducer

interface Iactions {
    type:string;
    value:any;
}
export interface Istate {
    count: number
}

const defaultState:Istate {
    count: 0
}

export default (state = defaultState, action: Iactions): Istate => {
    swtich(action.type){
        case 'add':
        	return {...state,count: state.count+1}
        default: 
        	return state;
    }
}

combineReducer

import { combineReducers } from "redux";
import User from "./reudcer";

export default combineReducers({
  User,
});

store

import { createStore, compose, applyMiddleware } from "redux";
import reducer from "./reudcers";
import thunk from "redux-thunk";
import { Istate } from "./reudcers/user"; //这个是为了在react-redux中的state设置

const composeEnhancers =
  typeof window === "object" && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
    ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
        // Specify extension’s options like name, actionsBlacklist, actionsCreators, serialize...
      })
    : compose;

const enhancer = composeEnhancers(applyMiddleware(thunk));

export interface StoreState {
  User: Istate;
}

const store = createStore(reducer, enhancer);

export default store;

注意: 这个地方会报错,说windows上面没有__REDUX_DEVTOOLS_EXTENSION_COMPOSE__这个属性

在根目录下面创建types目录,再创建index.d.ts

// 修改ReduxTools工具
interface Window extends REDUXTOOS {
  __REDUX_DEVTOOLS_EXTENSION_COMPOSE__:
    | string
    | __REDUX_DEVTOOLS_EXTENSION_COMPOSE__;
}

declare var window: Window;

组件上

import React from 'react'
import { connect } from 'react-redux'
import { StoreState } from 'src/store'   //引入store中导出的state数据类型
import { setUserInfo } from 'src/store/action'

const App:React.FC<{}> = props => {
    const { count } = props;
    return <div>{count}</div>
}

export default connect(
  (state: StoreState) => ({
      count: state.User.count
  }),
  (dispatch: any) => {
    return {
      addCount(count: number) {
        dispatch(setUserInfo(count));
      },
    };
})(App)

6.引入第三方包

在引入第三方包文件的时候 比如react-redux的时候

import {connect} from 'react-redux' ,会发现报错

当我们鼠标停留在react-redux上面的时候,会提示npm install @types/react-redux当我们安装完成之后,我们的项目文件才算完整

总结

TS第一开始上手会感觉非常的困难,十步一报错,而且代码量也增加了

但是TS确是很多大型项目的都乐意去选择的一个方向,感觉TS会越来越火,所以自己也在学习TS的过程中

分享一个自己正在写的 TS+Hooks简易版实战

posted @ 2020-05-05 14:16  残梦a  阅读(6436)  评论(3编辑  收藏  举报