React中常见的TypeScript定义使用

类型简述

一些React的内置类型

  • React.ReactElement ---- 使用React.createElement创建 可以理解为React中的JSX元素
  • React.ReactNode ----
    xxxx
    xxx的合法类型
  • React.CSSProperties —组件内联的style对象的类型
  • React.RefObject ----React.createRef创建的类型,只读不可改
  • React.MutableRefObject ----useRef创建的类型,可以修改

组件声明

组件声明分为类组件和函数组件

类组件
类组件使用定义主要为React.Component<P,S>和React.PureComponent<P,S,SS>

interface AppProps{
    value:string
}
interface AppState{
    count:number
}

class App extends React.Component<AppProps,AppStore>{
    static defaultProps = {
        value:''
    };
    state = {
        count:0
    }
}

React.Component<P,S> 这里P是props的类型,S是state的类型,可以写为React.Component,因为state的类型会自己推断
在上面PureComponent中还有个SS,这个ss是getSnapshotBeforeUpdate的返回值

函数组件

函数组件定义的方式简单来看两种,一种是使用React.FC,一种是直接给props写上定义

interface AppProps{
	value?:string
}
const App:React.FC<AppProps> = ({value="",children})=>{
//...
}

React.FC的意思是FunctionComponent
如果使用了React.FC,它在定义里就已经规定好了children的类型和函数的返回值 所以可以直接使用children
如果是直接给props写上定义 就需要自己定义children的类型

interface AppProps{
value?:string;
children?:React.ReactNode; //自己定义children的类型
}
function App({value="",children}:AppProps){
	return <>{children}</>
}	

使用function来定义而不是箭头函数的优点是可以使用泛型组件

Hooks声明

hooks的声明如果不知道如何用ts定义可以直接点进来看

useState
useState可以使用泛型传参或自动推断

const [state,setState] = useState('')//state的类型为为string,自动推断
const [state,setState] = useState<string>()//state的类型为string|undefined

//给初值
const [state,setState] = useState<string|null>(null)//state的类型为string | null

useRef
useRef同样也会自动推断

const ref = useRef("") //ref.current的类型为string
//泛型
type Value = {value:string}
const ref = useRef<Value>({value:""});
//ref为html元素
const ref = useRef<HTMLDivElement>(null)
return <div ref={ref}/>

需要注意的是如果ref为元素 那么初始值得写个null才不会报错

useReducer
useReducer相对来说要写得更多一点 可以自动推断,
所以不需要手动写泛型类型

//state 类型
interface ReducerState {
    value:String;
}

//action 类型
interface AnyAction {
    type:String;
    [key:string]:any
}

//reducer 函数
const reducer:React.Reducer<ReducerState,AnyAction> = (state,action)=>{
    switch(action.type){
        default: 
            return state;
    }
}
//初始值
const initialState:ReducerState = {value:""}

const [state,dispatch] = useReducer(reducer,initialState)

//state的类型为ReducerState
//dispatch的类型为React.Dispatch<AnyAction

Action也可以是多个不同的Action的联合类型

useImperativeHandle
useImperativeHandle 这个钩子可以把内部方法通过ref暴露出去, 用ts也是要写多一点 类型都需要标注清楚
所以需要使用到React.forwardRef,

//props
interface AppProps{
    value:string;
}

// useImperativeHandle获取到ref的类型
interface Handle{
    get:()=>string
}

const App = React.forwardRef<Handle,AppProps>(({value},ref)=>{
    //定义
   useImperativeHandle(ref,()=>({
       get:()=>`handle get value:${value}`
   }));
   return null
})

//使用
const handleRef = useRef<Handle>(null)
// handleRef.current?.get();
return <App value="hello" ref={handleRef}/> 

自定义hook需要注意的
有如下钩子

const useCustomHook = ()=>{
    const [state,setState] = useState('')
    const set = (value:string)=>{
        if(!value) return
        setState(value)
    }
    return [state,set]
}

//使用
const [state,setState] = useCustomHook()
setState('hello') // This expression is not callable

自定义钩子还需要自定义返回值才行

const useCustomHook = ()=>{}
const useCustomHook = ():[String,(value:string)=>viod]=>{}
React.forwardRef

React.forwardRef<T,P={}>只需要传props的类型和ref的类型,第一个T是ref的类型 P是props的类型

const App = React.forwardRef<HTMLDivElement,AppProps>(({value},ref)=>{
    return <div ref={ref}/>
})

//使用
const ref = useRef<HTMLDivElement>(null)
return <App value="hello" ref={ref}/>
React.ForwardRefRenderFunction

定义为该类型的函数可以放进React.forwardRef函数中作为参数


//定义
const forwardRender:React.ForwardRenderFunction<
HTMLDivElement,AppProps>=({value},ref)=>{
    return <div ref={ref}/>
}

const App = React.forwardRef(forwardRender)
// 使用
const ref = useRef<HTMLDivElement>(null)
return <App value="hello" ref={ref}/>
React.createContext

泛型有自动推断的功能 所以useContext就不需要再写上类型了

interface ContextType {
    getPrefixCls:(value:string)=>string
}

const context = React.createContext<ContextType>({
    getPrefixCls:(value)=>`prefix-${value}`
})

const App = ()=>{
    const {getPrefixCls} = useContext(context)
    getPrefixCls("App") //prefix-App
    return null
}
React.cloneElement

如果使用的React.FC定义的组件 他的children类型默认是React.ReactNode,需要显式转为React.ReactElement

const App:React.FC = ({children})=>{
    return React.cloneElement(children as React.ReactElement,{value:'hello'})
}

//也可以覆写定义
const App:React.FC<{children:React.ReactElement}>=({children})=>{
    return React.cloneElement(children,{value:'hello'})
}
React.ComponentType

通过React.ComponentType

定义的组件可以将变量名传入组件,在组件内调用,高阶组件通常会使用

interface AppProps{
    value:string
}
const App:React.FC<AppProps>=(props)=>{
    return null
}

//React.ComponentType定义组件
function HOC<T>(Component:React.ComponentType<T>){
    return function(props:T){
        return <Component {...props}/>
    }
}
const WrappedComponent = HOC(App)
//调用
<WrappedComponent value="hello"/>
泛型参数的组件

泛型参数的组件是typescript2.9 版本新增的 第一次看见是在ant-design里
一个简单的例子就是Select组件

<Select <number>>
    <Select.Option value={1}>
        1
    </Select.Option>
     <Select.Option value={2}>
     1
 </Select.Option>
</Select>
类组件的定义
// 定义泛型参数的组件
class GenericComponent<P> extends React.Component<P>{
    internalProp:P;
    constructor(props:P){
        super(props);
        this.internalProp = props
    }
    render(){
        return null
    }
}

type Props = {a:Number;b:string}
<GenericComponent<Props> a={10} b="hi"/> //ok
<GenericComponent<Props> a={10} b={20}/> //Error
函数组件的定义
function GenericComponent<P>(props:P){
    const internalProp = useRef(props)
    return null
}

箭头函数的组件在特定条件也能用泛型


//这样会解析报错
const  GenericComponent = <P>(props:P) => {
    const internalProp = useRef(props)
    return null
}


{/* 泛型必须使用extends 关键字才能解析 */}
const GenericComponent = <P extends any>(props:P) =>{
    const internalProp = useRef(props)
    return null
}

函数组件写起来可简洁太多了…

事件处理

也是多种多样

const App = ()=>{
    //React.MouseEventHandler
    const onClick: React.MouseEventHandler<HTMLInputElement> = (e)=>{
        console.log(e.currentTarget.value);
    }
    //React.ChangeEventHandler
    const onChange:React.ChangeEventHandler<HTMLInputElement>=(e)=>{
        console.log(e.currentTarget.value);
    }
    //React.FocusEventHandler
    const onFocus:React.FocusEventHandler<HTMLInputElement>=(e)=>{
        console.log(e.currentTarget.value);
    }
    return <input onClick={onClick} onChange={onChange} onFocus={onFocus}/>
}   

如果有事件不清楚该如何定义类型,可以点组件上的事件名去看看定义

需要注意的是只有e.currentTarget才会有对应的元素类型,e.target是没有的,它的类型是EventTarget

ts自带了一些工具泛型,比如Omit、Pick,在开发的时候还是有帮助

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值