使用 TypeScript 在 React 中向 Refs 添加类型

将类型添加到 useRef 钩子最初可能有点令人困惑,让我们看看为什么会这样:

import {useEffect, useRef} from 'react';

export function RefDemo() {
  const inputRef = useRef();

  useEffect(() => {
    inputRef.current.focus();
  }, []);

  return (
    <div>
      <input ref={inputRef} />
    </div>
  );
}

在上面的代码片段中,我们遇到了几个错误——当我们将鼠标悬停在 ref 属性上时,错误非常冗长且令人困惑——总而言之,inputRef.current 可能未定义并且无法分配给 HTMLInputElement。

为了修复错误,我们必须做几件事:

一、将泛型添加到 useRef 钩子并传入 HTMLInputElement 作为类型。

- const inputRef = useRef();
+ const inputRef = useRef<HTMLInputElement>();

我们如何获得名称是当我们将鼠标悬停在输入元素上时,我们会看到如下内容:

(property) JSX.IntrinsicElements.input: React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>

我们可以看到类型是 HTMLInputElement。 我们还可以在 VSCode 中控制 click 并读取声明文件以获取任何元素的类型。

二、即使在添加了泛型之后,typescript也会告诉我们——我们实际上可能不会将 ref 传递给输入元素,因此因为我们没有将初始值传递给 useRef,所以 ref 的值可能是未定义的。 所以我们必须告诉 typescript inputRef.current 的值被初始化为 null 并且是 null 或者 HTMLInputElement。

import {useEffect, useRef} from 'react';

export function RefDemo() {
  const inputRef = useRef<HTMLInputElement | null>(null);

  useEffect(() => {
    inputRef?.current?.focus();
  }, []);

  return (
    <div>
      <input ref={inputRef} />
    </div>
  );
}

因为 typescript 不知道我们是否要将 ref 分配给输入元素,所以我们仍然必须有条件地在 ref 上调用 focus() 函数。