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

相关推荐
腾讯TNTWeb前端团队3 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰7 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪7 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪7 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy8 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom8 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom8 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom8 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom9 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom9 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试