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

相关推荐
诗书画唱几秒前
【前端面试题】JavaScript 核心知识点解析(第二十二题到第六十一题)
开发语言·前端·javascript
excel7 分钟前
前端必备:从能力检测到 UA-CH,浏览器客户端检测的完整指南
前端
前端小巷子14 分钟前
Vue 3全面提速剖析
前端·vue.js·面试
悟空聊架构21 分钟前
我的网站被攻击了,被干掉了 120G 流量,还在持续攻击中...
java·前端·架构
CodeSheep22 分钟前
国内 IT 公司时薪排行榜。
前端·后端·程序员
尖椒土豆sss26 分钟前
踩坑vue项目中使用 iframe 嵌套子系统无法登录,不报错问题!
前端·vue.js
遗悲风27 分钟前
html二次作业
前端·html
江城开朗的豌豆30 分钟前
React输入框优化:如何精准获取用户输入完成后的最终值?
前端·javascript·全栈
CF14年老兵30 分钟前
从卡顿到飞驰:我是如何用WebAssembly引爆React性能的
前端·react.js·trae
画月的亮34 分钟前
前端处理导出PDF。Vue导出pdf
前端·vue.js·pdf