最近一段时间在做 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
,所以user
为null
,这样使用到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
的类型使用到了typeof
,typeof
的作用是获取到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;
子组件中接受两个参数props
和ref
类型分别是propsType
和any
(这里注意位置别搞混),暴露给父组件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