TypeScript && React

Posted v587chinese

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TypeScript && React相关的知识,希望对你有一定的参考价值。

环境搭建

我们当然可以先用脚手架搭建React项目,然后手动配置成支持TypeScript的环境,虽然比较麻烦,但可以让你更清楚整个过程。这里比较麻烦,就不演示了,直接用命令配置好。

npx create-react-app appname --typescript

可以安装一些自己需要的库及其声明文件,例如react-router-dom、axios、ant Design等。如果要安装ant design,还需要在开发环境库中安装一些依赖库,以帮助实现按需加载。

使用

有类型约束的函数组件

import React from "react";
import  Button  from "antd";

interface Greeting 
   name: string;
   firstName?: string;
   lastName?: string;


// 没有使用React.FC
const HelloOld = (props: Greeting) => <Button>你好props.name</Button>;

// 使用React.FC泛型类型
const Hello: React.FC<Greeting> = (props) => 
   return (
      <Button>Hello props.name</Button>
   )
;

export  Hello, HelloOld ;

定义函数组件时,使用React.FC与不使用没有太多区别,没有为我们带来明显的好处,建议使用常规定义方式。

有类型约束的类组件

import React,Fragment from "react";
import  Button  from "antd";

interface Greeting 
   name: string;
   firstName?: string;
   lastName?: string;

interface State 
   count: number


// 泛型类型,第一个传入参数约束属性props,第二个约束状态state(内部数据)
class HelloClass extends React.Component<Greeting, State> 
   state: State = 
      count: 0
   ;
   static defaultProps =   // 属性默认值
      firstName: "",
      lastName: "",
   ;

   render() 
      return (
         <Fragment>
            <p>点击了this.state.count次</p>
            <Button onClick=()=>this.setState(count: this.state.count+1)>Hellothis.props.nameClass</Button>
         </Fragment>
      );
   


export default HelloClass;

有类型约束的高阶组件

import React from "react";
import HelloClass from "./HelloClass";

interface Loading 
   loading: boolean;


function HelloHoc<P>(params?: any) 
   return function<P>(WrappedComponent: React.ComponentType<P>)  // P表示被包装组件的属性的类型
      return class NewComponent extends React.Component<P & Loading> // 这里使用交叉类型,为新组件增加一些属性,接口Loading定义了新增的属性声明
         render()
            return this.props.loading ? <div>Loading</div> : <WrappedComponent ...this.props as P/>

         
      
   


export default HelloHoc()(HelloClass);

高阶组件在ts中使用会有比较多的类型问题,解决这些问题通常不会很顺利,而且会存在一些已知的bug,这不是高阶组件本身的问题,而是React声明文件还没有很好地兼容高阶组件的类型检查,更好的方式是使用Hooks

有类型约束的Hooks

import React,  useState, useEffect  from "react";
import  Button  from "antd";

interface Greeting 
   name: string;
   firstName?: string;
   lastName?: string;


const HelloHooks = (props: Greeting) => 
   const [ count, setCount ] = useState(0); // 设了初值,所以不用定义类型
   const [ text, setText ] = useState<string | null>(null);

   useEffect(()=>
      count > 5 && setText("休息一下");
   ,[count]); // 第二个参数的作用是,只有当count改变的时候,函数内的逻辑才会执行。

   return (
      <>
         <p>你点击了Hooks count 次 text</p>
         <Button onClick=()=>setCount(count+1)>props.name</Button>
      </>
   );
;

export default HelloHooks;

事件绑定

class HelloClass extends React.Component<Greeting, State> 
   state: State = 
      count: 0
   ;

   clickHandle = (e: React.MouseEvent) =>  // 事件对象e的类型使用内置的合成事件。在回调函数中,e的属性都会无效
      e.persist(); // 将该事件从池中删除合成事件,可以正常使用
      console.log(e);
      // this.setState(count: this.state.count+1)
   ;

   inputHandle = (e: React.FormEvent<htmlInputElement>) => 
      // e.persist();
      console.log(e.currentTarget.value); // 此时编译器报错,认为没有value属性,需要指定<HTMLInputElement>泛型类型
      // console.log(e.target.value); // 仍然不行
   ;

   render() 
      return (
         <Fragment>
            <p>点击了this.state.count次</p>
            <Button onClick=this.clickHandle>Hellothis.props.nameClass</Button>
            <input onChange=this.inputHandle/>
         </Fragment>
      );
   

 

以上是关于TypeScript && React的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript && React

为啥在 Typescript 泛型中使用 '&'

Typescript & ReactJS 如何动态设置状态

React useContext & Typescript:不是数组类型

Jest & TypeScript:VS Code 找不到名称

Typescript & React:在组件之间传递道具与默认道具