TypeScript学习笔记(十三)

100 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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([])

image.png

如果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。

image.png

const inputRef = useRef<HTMLInputElement>(null)
const get = () => {
  console.log(inputRef.current?.value)
}

如何获取一个DOM对象的类型,鼠标直接移动到该元素上,就会显示出来该元素的类型。

image.png