React 遇到 TS 必须掌握的Hook类型定义

最近一段时间在做 React 项目,用的是TS语言,第一次尝试用TS写项目,刚开始用静态类型写前端还不太适应,处处碰壁。我自己总结了一些常见的Hook类型定义,希望能帮助到大家

useState

出场率极高的Hook,之前也在文章中给大家介绍过 Vue转React 3分钟学会useState 大家有兴趣可以看看

ts 复制代码
import { useState } from "react";

type userType = {
  name: string,
  age?: number
}

function App() {
  const [user, setUser] = useState<userType | null>(null)
  function handle() {
    setUser({
      name: '张三',
      age: 18
    })
    console.log('33')
  }
  return (
    <div className="App">
      {user?.name} {user?.age}
      <button onClick={handle}>测试</button>
    </div>
  );
}

export default App;

userType是自定义的类型,意思是对象里面有两个参数name,age,age可以为空(?是指可空)

useState<userType | null>()Hook的返回值是userType类型或null,因为初始值null,所以usernull,这样使用到user就会有相应语法提示

useRef

DOM

ts 复制代码
import { useRef } from "react";

function App() {
  const ref = useRef<HTMLDivElement>(null)
  function handle() {
    console.log(ref.current?.innerHTML)
  }
  return (
    <>
      <div ref={ref} className="App" onClick={handle}>测试</div>
    </>
  );
}

export default App;

HTMLDivElement是 React 提供的类型,代表类型是一个 DOM 元素中的 DIV 元素,在使用ref.current的时候有更好的代码提示 类似的 DOM 接口:

  • HTMLInputElement(input) 代表HTML中的输入控件,如文本框、单选框、复选框等
  • HTMLButtonElement(button) 代表HTML中的按钮元素
  • HTMLImageElement(img) 代表HTML中的图像元素
  • HTMLAnchorElement(a) 代表HTML中的超链接元素
  • HTMLVideoElement(video) 代表HTML中的视频元素
  • HTMLAudioElement(audio) 代表HTML中的音频元素
  • HTMLIFrameElement(iframe) 代表HTML中的内联框架元素
  • HTMLOptionElement(option) 代表HTML中的选项元素
  • HTMLTableElement(table) 代表HTML中的表格元素
  • HTMLFormElement(form) 代表HTML中的表单元素

定时器

ts 复制代码
import { useRef, useEffect } from "react";

function App() {
  const ref = useRef<number | null>(null)
  useEffect(() => {
    ref.current = window.setTimeout(() => {
      console.log('33')
    }, 1000)
    return clearTimeout(ref.current)
  }, [])
  return (
    <>
      <div className="App">测试</div>
    </>
  );
}

export default App;

ref.current作为定时器的引用,可以保存定时器的标识符或引用。

useReducer

ts 复制代码
import { useReducer } from 'react';

type ActionType = {
  type: 'ADD'
}

const initialState = {
  count: 0
}

function reducer(state: typeof initialState, action: ActionType) {
  const newState = {...state};
  if(action.type === 'ADD') {
    newState.count = state.count + 1;
  }
  return newState;
}

function App() {
  const [ state, dispatch ] = useReducer(reducer, initialState)
  return (
    <>
      <button onClick={() => {dispatch({
        type: 'ADD'
      })}}>ADD</button>
      <div>{state.count}</div>
    </>
  );
}

export default App;

reducer函数中形参定义state的类型使用到了typeoftypeof的作用是获取到initialState的类型定义

forwardRef & useImperativeHandle

这两个 Hook 组合一般用于在子组件定义事件,在父组件中调用,实现父子组件交互

js 复制代码
import { forwardRef, ReactNode, useImperativeHandle, useRef } from "react";

type propsType = {
  children: ReactNode
}
type refType = {
  start: () => void
}

const Child = forwardRef<any, propsType>((props, ref) => {
  useImperativeHandle(ref, () => {
    return {
      start(){
        console.log('start')
      }
    }
  })
  return (
    <div>{props.children}</div>
  )
})

function App() {
  const ref = useRef<refType>(null!)

  return (
    <>
      <button onClick={() => ref.current.start()}>按钮</button>
      <Child ref={ref}>测试</Child>
    </>
  );
}

export default App;

子组件中接受两个参数propsref类型分别是propsTypeany(这里注意位置别搞混),暴露给父组件start方法,在父组件中想有语法提示,必须在声明ref的时候指定类型refType

useContext

ts 复制代码
import { createContext, useContext, useState } from "react";

type geenderType = {
  sex: '男' | '女'
}
const GenderValue = createContext<geenderType>({sex: '男'})

function Child() {
  const dender = useContext(GenderValue)
  return (
    <div>{dender.sex}</div>
  )
}

function App() {
  const [ sex, setSex ] = useState<geenderType>({sex: '男'})
  return (
    <GenderValue.Provider value={sex}>
      <button onClick={() => setSex({sex: '男'})}>按钮</button>
      <Child />
    </GenderValue.Provider>
  );
}

export default App;

创建Context对象的时候指定了类型为geenderType,并赋初始值,注意在 App 组件中赋值的时候变量也应该遵守geenderType定义的类型格式,这样在更改的时候只能是男或者女,避免出现其他值

事件类型

  • React.MouseEvent 鼠标点击事件
  • React.WheelEvent 鼠标滚轮事件
  • React.ToutchEvent 移动端触摸事件
  • React.ChanceEvent 输入框改变事件
  • React.FocusEvent 焦点事件
  • React.FormEvent 表单事件
  • React.KeyboardEvent 键盘事件
ts 复制代码
import React from "react";

function App() {
  function handle(e: React.MouseEvent) {
    console.log(e.target)
  }
  
  return (
    <div onClick={handle}>hello word</div>
  );
}

export default App;
ts 复制代码
import React from "react";

function App() {
  function handle(e: React.ChangeEvent<HTMLInputElement>) {
    console.log(e.target.value)
  }
  
  return (
    <input onChange={handle}>hello word</input>
  );
}

export default App;

React.ChangeEvent<HTMLInputElement>加上HTMLInputElement类型输入e.target会提示value属性,配合 DOM 接口类型可以提供更智能的语法提示

总结

TS 类型写得好可以提高代码质量,减少错误,增强代码的可维护性和可读性,从而提升整个项目的开发效率和稳定性

以上就是常见 Hook 的类型定义,如果有遗漏的欢迎大家评论留言,另外交给大家一个检验TS类型定义是否标准的一个方法,鼠标放在变量上看显示的类型是否跟数据的类型一致,而不是any

相关推荐
彭世瑜22 分钟前
ts: TypeScript跳过检查/忽略类型检查
前端·javascript·typescript
FØund40423 分钟前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html
Backstroke fish23 分钟前
Token刷新机制
前端·javascript·vue.js·typescript·vue
小五Five25 分钟前
TypeScript项目中Axios的封装
开发语言·前端·javascript
小曲程序25 分钟前
vue3 封装request请求
java·前端·typescript·vue
临枫54125 分钟前
Nuxt3封装网络请求 useFetch & $fetch
前端·javascript·vue.js·typescript
前端每日三省27 分钟前
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
开发语言·前端·javascript
小刺猬_98527 分钟前
(超详细)数组方法 ——— splice( )
前端·javascript·typescript
渊兮兮28 分钟前
Vue3 + TypeScript +动画,实现动态登陆页面
前端·javascript·css·typescript·动画
鑫宝Code29 分钟前
【TS】TypeScript中的接口(Interface):对象类型的强大工具
前端·javascript·typescript