useEffect
在TS中,useEffect的使用和JS完全一致
useEffect(()=>{
},[需要监听的数据])
useEffect的类型声明格式
// ? 表示可选
// DependencyList 是一个 Readonly any[]
function useEffect(effect: EffectCallback, deps?: DependencyList): void;
useState
useState的类型声明格式
function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];
标准用法(Js中的用法)
useState接收一个泛型参数,用于指定初始值的类型
示例:
// 使用泛型
const [name, setName] = useState<string>('张三')
const [age, setAge] = useState<number>(28)
const [isProgrammer, setIsProgrammer] = useState<boolean>(true)
// 如果你在set函数中的参数不符合声明的变量类型,程序会报错
<button onClick={() => setName(100)}>按钮</button> // 报错
简单用法
在使用useState的时候,只要提供了初始值,typescript会自动根据初始值进行类型推断,因此useState的泛型参数可以省略(就是TS的类型推论)
示例:
const [name, setName] = useState('张三')
const [age, setAge] = useState(28)
const [isProgrammer, setIsProgrammer] = useState(true)
注意:useState本身是需要接受泛型参数的,但是由于TS的类型推论机制,所以这个泛型参数就可以省略
进阶用法
场景:发送请求向后台服务器获取数据
JS初始写法
import { useEffect, useState } from 'react'
import axios from 'axios'
export default function App() {
// 存放频道列表数据
const [list, setList] = useState([])
useEffect(() => {
const fetchData = async () => {
const res = await axios.get('http://geek.itheima.net/v1_0/channels')
setList(res.data.data.channels)
}
fetchData()
}, [])
return (
<div>
<ul>
{list.map((item) => {
return <li key={item.id}>{item.name}</li> {/*这里会报错:*/}
})}
</ul>
</div>
)
}
此时会遇到错误,
解决方案:
-
提前给初始值,便于类型推导
const [list, setList] = useState([{id:1, name: 'test'}]) -
补充泛型参数:any大法
const [list, setList] = useState<any[]>([]) -
补充泛型参数:按接口返回值自定义类型
type Channel = { id: number, name: string}[]const [list, setList] = useState<Channel[]>([])
useRef
useRef的类型声明格式:
function useRef<T>(initialValue: T): MutableRefObject<T>;
interface MutableRefObject<T> {
current: T;
}
注意:
useRef的泛型参数用于指定current属性的值的类型
使用useRef操作DOM,需要明确指定所操作的DOM的具体的类型,否则current属性会是null
const Ref=useRef<HTML'DOM元素类型'ELEment>(null)
示例:
const inputRef = useRef<HTMLInputElement>(null) //null可以代表对象类型
在jsx中,鼠标直接移动到该元素上,就会显示出来该元素的类型
useSelector
useSelector接收两个泛型参数
-
第一个泛型类型:TState的默认值是DefaultRootState(就是{})用于指定state的类型
-
第二个泛型类型:TSelected用于指定返回值的类型
//useSelector类型声明格式 export function useSelector<TState = DefaultRootState, TSelected = unknown>( selector: (state: TState) => TSelected, equalityFn?: (left: TSelected, right: TSelected) => boolean ): TSelected;
//类型为 unknown 时,不能使用该类型的属性和方法但是可以为其赋值,直接使用会报错
解决方案1:
- 指定泛型类型
示例:
const todos = useSelector<{todos:[]} ,{id:number, name:string,isDone:boolean}[]>(state => state.todos)
解决方案2:
- 直接指定回调函数的形参类型
示例:
const todos = useSelector((state: {todos:{id:number, name:string,isDone:boolean}[]}) => state.todos)
useDispatch
基本用法
const dispatch = useDispatch() //此时与JS中的写法一直,用法也是一样的
进阶用法
useDispatch可以接收一个泛型参数用于指定Action的类型
示例:
import { Dispatch } from "react"
import { useSelector, useDispatch } from "react-redux"
import { RootStateType } from '../store'
export default function Home() {
const dispatch = useDispatch<Dispatch<{type:string,payload:any}>>()
dispatch({
type: 'abc',
payload: 123
})
useHistory
作用:可以用来做路由之间的跳转,并且在跳转时可以指定跳转参数state的类型
useHistory类型声明格式
export function useHistory<HistoryLocationState =
H.LocationState>(): H.History<HistoryLocationState>;
路由传参
语法:
const history = useHistory()
// 方式1
history.push('/home', { a:1 })
// 方式2
history.push({pathname: '/home', state:{a:1 }})
如果希望跳转传参时,有指定的格式,可以给useHistory泛型提供类型参数
const history = useHistory<{a: number }>()
获取路由参数
场景:通过useLocation 来获取上一个页面传递的参数。
js的基本格式:
// 原来js的写法
import { useLocation } from 'react-router'
const location = useLocation()
const aa = location.state.a
// 这里的a就是上一个页面中通过state传进来的
进阶用法
通过 useHistory可以通过泛型参数来指定state的类型
import { useLocation } from 'react-router'
export default function Home() {
const location = useLocation<{ a: string }>()
const a = location.state?.a
}
useParams
作用:useParams接收一个泛型参数,用于指定params对象的类型
useParams类型声明格式
export function useParams<Params extends { [K in keyof Params]?: string } = {}>(): Params;
注意:使用useParams中的属性时,需提前定义一个泛型参数,由useParams来接受,直接使用会报错