useState
简单场景
简单场景下,可以使用TS的自动推断机制,不用特殊编写类型注解,运行良好
1 2 3 4
| const [val, toggle] = React.useState(false)
|
复杂场景
复杂数据类型,useState支持通过泛型参数指定初始参数类型以及setter函数的入参类型
1 2 3 4 5 6 7 8 9 10 11
| type User = { name: string age: number } const [user, setUser] = React.useState<User>({ name: 'jack', age: 18 })
setUser(newUser)
|
没有具体默认值
实际开发时,有些时候useState的初始值可能为null或者undefined,按照泛型的写法是不能通过类型校验的,此时可以通过完整的类型联合null或者undefined类型即可
1 2 3 4 5 6 7 8 9
| type User = { name: String age: Number } const [user, setUser] = React.useState<User>(null)
const [user, setUser] = React.useState<User | null>(null)
|
useRef
在TypeScript的环境下,useRef 函数返回一个只读 或者 可变 的引用,只读的场景常见于获取真实dom,可变的场景,常见于缓存一些数据,不跟随组件渲染,下面分俩种情况说明
获取dom
获取DOM时,通过泛型参数指定具体的DOM元素类型即可
1 2 3 4 5 6 7 8 9 10 11
| function Foo() { const inputRef = useRef<HTMLDivElement>(null)
useEffect(() => { inputRef.current.focus() })
return <div ref={inputRef}>etc</div> }
|
如果你可以确保divRef.current 不是null,也可以在传入初始值的位置
1 2 3 4
| const divRef = useRef<HTMLDivElement>(null!)
doSomethingWith(divRef.current)
|
稳定引用存储器
当做为可变存储容器使用的时候,可以通过泛型参数指定容器存入的数据类型, 在还为存入实际内容时通常把null作为初始值,所以依旧可以通过联合类型做指定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| interface User { age: number }
function App(){ const timerRef = useRef<number | undefined>(undefined) const userRes = useRef<User | null> (null) useEffect(()=>{ timerRef.current = window.setInterval(()=>{ console.log('测试') },1000) return ()=>clearInterval(timerRef.current) }) return <div> this is app</div> }
|
为Props添加类型
props作为React组件的参数入口,添加了类型之后可以限制参数输入以及在使用props有良好的类型提示
使用interface接口
1 2 3 4 5 6 7 8
| interface Props { className: string }
export const Button = (props:Props)=>{ const { className } = props return <button className={ className }>Test</button> }
|
使用自定义类型Type
1 2 3 4 5 6 7 8
| type Props = { className: string }
export const Button = (props:Props)=>{ const { className } = props return <button className={ className }>Test</button> }
|
为Props的chidren属性添加类型
children属性和props中其他的属性不同,它是React系统中内置的,其它属性我们可以自由控制其类型,children属性的类型最好由React内置的类型提供,兼容多种类型
1 2 3 4 5 6 7 8
| type Props = { children: React.ReactNode }
export const Button = (props: Props)=>{ const { children } = props return <button>{ children }</button> }
|
:::warning
说明:React.ReactNode是一个React内置的联合类型,包括 React.ReactElement 、string、number React.ReactFragment 、React.ReactPortal 、boolean、 null 、undefined
:::
为事件prop添加类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| type Props = { onGetMsg?: (msg: string) => void }
function Son(props: Props) { const { onGetMsg } = props const clickHandler = () => { onGetMsg?.('this is msg') } return <button onClick={clickHandler}>sendMsg</button> }
function App() { const getMsgHandler = (msg: string) => { console.log(msg) } return ( <> <Son onGetMsg={(msg) => console.log(msg)} /> <Son onGetMsg={getMsgHandler} /> </> ) }
export default App
|
为事件handle添加类型
为事件回调添加类型约束需要使用React内置的泛型函数来做,比如最常见的鼠标点击事件和表单输入事件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function App(){ const changeHandler: React.ChangeEventHandler<HTMLInputElement> = (e)=>{ console.log(e.target.value) } const clickHandler: React.MouseEventHandler<HTMLButtonElement> = (e)=>{ console.log(e.target) }
return ( <> <input type="text" onChange={ changeHandler }/> <button onClick={ clickHandler }> click me!</button> </> ) }
|