React创建项目方式
- react脚手架:create-react-app 项目名 --template typescript
- 基于vite创建项目:npm init vite@latest 项目名 – --template react-ts
useState自动推导
通常React会根据传入useState的默认值来自动推导类型,不需要显示标注类型
const [value, toggle] = useState(false)
- value:类型为boolean
- toggle:参数类型为boolean
useState传递泛型参数
useState本身是一个泛型参数,可以传入具体的自定义类型
type User = { name: string, age: number }
const [user, setUser] = useState()
- 限制useState函数参数的初始值必须满足类型为:User | () => User
- 限制setUser函数的参数必须满足类型为:User | () => User | undefined
- user状态数据具备User类型相关的类型提示
useState初始值为null
当我们不知道状态的初始值是什么,将useState的初始值为null是一个常见的做法,可以通过具体类型联合null来做显式注解
type User = { name: string, age: number }
const [user, setUser] = useState<User | null>(null)
- 限制useState函数参数的初始值可以是User | null
- 限制setUser函数的参数类型可以是User | null
- 为了类型安全,可选链做类型守卫:user?.name
props 与 Typescript
props 与 Typescript基础使用
为组件prop添加类型,本质是给函数的参数做类型注解,可以使用type对象类型或者interface接口来做注解
// 方式一:type
// type Props = {
// className: string
// }
// 方式二:interface
interface Props {
className: string,
}
function Button(props: Props) {
const {className} = props
return <button className={className}>点击</button>
}
function App() {
return (
<>
<Button className={'test'}/>
</>
)
}
export default App
props与TypeScript 为children添加类型
children是一个比较特殊的prop,支持多种不同类型数据的传入,需要通过一个内置的ReactNode类型来做注解
注解之后,children可以是多种类型,包括:React.ReactElement、string、number、React.ReactFragment、React.ReactProtal、boolean、null、undefined
import * as React from "react";
// type
// type Props = {
// className: string
// }
// interface
interface Props {
className: string,
children: React.ReactNode
}
function Button(props: Props) {
const {className, children} = props
return <button className={className}>{children}</button>
}
function App() {
return (
<>
<Button className={'test'}>点击</Button>
<Button className={'test'}><span>aaa</span></Button>
</>
)
}
export default App
propTypes 与 TypeScript 为事件prop添加类型
组件经常执行类型为函数的prop实现子传父,这类prop重点在于函数参数类型的注解
1.在组件内部调用时需要遵守类型的约束,参数传递需要满足要求
2.绑定prop时如果绑定内联函数直接可以推断出参数类型,否则需要单独注解匹配的参数类型
type Props = {
onGetMsg?: (msg: string) => void
}
function Son(props: Props) {
const {onGetMsg} = props
const clickHandler = () => {
onGetMsg?.('hello')
}
return <button onClick={clickHandler}>点击</button>
}
function App() {
const getMsgHandler = (msg:string) => {
console.log(msg)
}
return (
<>
<Son onGetMsg={(msg) => console.log(msg)}></Son>
<Son onGetMsg={getMsgHandler}></Son>
</>
)
}
export default App
useRef与Typescript
useRef与Typescript 获取dom
获取dom的场景,可以直接把要获取的dom元素当成泛型参数传递给useRef,可以推导出.current属性的类型
import {useEffect, useRef} from "react";
function App() {
const domRef = useRef<HTMLInputElement>(null)
useEffect(()=>{
domRef.current?.focus()
},[])
return (
<>
<input ref={domRef}/>
</>
)
}
export default App
useRef与Typescript 引用稳定的存储器
把useRef当成稳定的存储器使用的场景可以通过泛型传入联合类型来做,比如定时器的场景
import {useEffect, useRef} from "react";
function App() {
const timerRef = useRef<number | undefined>(undefined)
useEffect(()=>{
timerRef.current = setInterval(() => {
console.log('run')
},1000)
return () => clearInterval(timerRef.current)
},[])
return (
<>
hello
</>
)
}
export default App