持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情
前言
大家好呀,我是L同学。在上篇文章TypeScript学习笔记(十二)—— 类型声明文件第三方库中,我们学习了TypeScript的相关知识点,包括类型声明文件-第三方库,类型声明文件-自定义等相关知识点。在本篇文章中,我们将学习TypeScript的相关知识点,包括useState的使用、useEffect的使用、useState 进阶用法等内容。
React与Typescript配合使用
useState的使用
useState接收一个泛型参数,用于指定初始值的类型。useState的源码如下。
/**
* Returns a stateful value, and a function to update it.
*
* @version 16.8.0
* @see https://reactjs.org/docs/hooks-reference.html#usestate
*/
function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];
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的类型推断,在使用useState的时候,只要提供了初始值,typescript会自动根据初始值进行类型推断,因此useState的泛型参数可以省略。
export default function App() {
const [name, setName] = useState('张三')
const [age, setAge] = useState(28)
const [isProgrammer, setIsProgrammer] = useState(true)
return (
<div>
<button onClick={() => setName(100)}>按钮</button>
</div>
)
}
useEffect的使用
useEffect是用于我们管理副作用(例如 API 调用)并在组件中使用 React 生命周期的。
useEffect的源码
/**
* Accepts a function that contains imperative, possibly effectful code.
*
* @param effect Imperative function that can return a cleanup function
* @param deps If present, effect will only activate if the values in the list change.
*
* @version 16.8.0
* @see https://reactjs.org/docs/hooks-reference.html#useeffect
*/
function useEffect(effect: EffectCallback, deps?: DependencyList): void;
useEffect函数不涉及到任何泛型参数,在typescript中使用和javascript中使用完全一致。
useEffect(() => {
// 给 window 绑定点击事件
const handleClick = () => {
console.log('哈哈哈')
}
window.addEventListener('click', handleClick)
return () => {
// 给 window 移除点击事件
window.addEventListener('click', handleClick)
}
}, [])
useState 进阶用法
现在我们有一个需求发送请求获取频道列表数据,并且渲染。useState如果没有提供具体类型的初始值,是需要使用泛型参数指定类型的。
我们通过list数组来存放频道列表数据。如果给useState的泛型参数直接指定为一个[],那将会得到一个never类型的数据,渲染的时候会出问题。
const [list, setList] = useState([])
如果useState的初始值是一个复杂的数据类型,需要给useState指定泛型参数。
import { useEffect, useState } from 'react'
import axios from 'axios'
type Res = {
id: number
name: string
}[]
export default function App() {
// 存放频道列表数据
const [list, setList] = useState<Res>([])
useEffect(() => {
const fetchData = async () => {
const res = await axios.get('http://xxx/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>
)
}
useRef的使用
useRef 接收一个泛型参数,源码如下。
/**
* `useRef` returns a mutable ref object whose `.current` property is initialized to the passed argument
* (`initialValue`). The returned object will persist for the full lifetime of the component.
*
* Note that `useRef()` is useful for more than the `ref` attribute. It’s handy for keeping any mutable
* value around similar to how you’d use instance fields in classes.
*
* @version 16.8.0
* @see https://reactjs.org/docs/hooks-reference.html#useref
*/
function useRef<T>(initialValue: T): MutableRefObject<T>;
interface MutableRefObject<T> {
current: T;
}
useRef的泛型参数用于指定current属性的值的类型。如果使用useRef操作DOM,需要明确指定所操作的DOM的具体的类型,否则current属性会是null。
const inputRef = useRef<HTMLInputElement>(null)
const get = () => {
console.log(inputRef.current?.value)
}
如何获取一个DOM对象的类型,鼠标直接移动到该元素上,就会显示出来该元素的类型。