如何在函数和类组件中使用React refs与TypeScript

761 阅读2分钟

在这篇文章中,我们将介绍如何在函数和类组件中使用React refs与TypeScript:

React Refs with TypeScript

在函数组件中创建强类型的 refs

useRef 钩子可以用来访问一个元素的所有属性和方法:

const element = React.useRef(null);
// can access all the properties and methods of `element` via `element.current` 
...
return (
  <SomeElement ref={element} />
);

当我们需要在一个元素上调用方法时,通常会用到它,下面是一个例子:

function Search() {
  const input = React.useRef(null);
  React.useEffect(() => {
    if (input.current) {
      input.current.focus();
    }
  }, []);
  return (
    <form>
      <input ref={input} type="search" />
    </form>
  );
};

当组件第一次渲染时,我们正在对一个input 设置焦点。

如果严格模式开启,input.current 的类型被推断为null ;否则,它被推断为any 。如果严格模式开启,在引用input.current 时也会发生类型错误。

不太理想。😞

我们可以通过传递一个通用类型参数来明确定义从useRef 返回的元素的类型:

const element = React.useRef<ElementType>(null);

因此,我们可以在Search 组件中显式地输入ref,如下所示:

const input = React.useRef<HTMLInputElement>(null);

现在类型错误消失了。😃

在类组件中创建强类型的引用

让我们把Search 组件实现为一个类组件,下面是第一次尝试:

class Search extends React.Component {
  private input = React.useRef<HTMLInputElement>(null);
  
  componentDidMount() {
    if (this.input.current) {
      this.input.current.focus();
    }
  }
 
  render() {
    return (
      <form>
        <input ref={this.input} type="type" />
      </form>
    );
  }
}

虽然useRef 钩子不能在类组件中使用。😞

在类组件中,我们可以使用createRef 来获得一个元素的引用。我们可以用它来修改我们对Search 组件的实现:

class Search extends React.Component {
  private input = React.createRef(); 
  componentDidMount() {
    if (this.input.current) {
      this.input.current.focus();
    }
  }
 
  render() {
    return (
      <form>
        <input ref={this.input} type="type" />
      </form>
    );
  }
}

虽然输入元素的类型被推断为unknown 。这意味着当this.input.current 被引用时,我们会得到一个类型错误。😞

我们可以通过传递一个通用类型参数来明确定义从createRef 返回的元素的类型:

React.createRef<ElementType>();

下面是Search 组件的一个修订的、更强类型的版本:

class Search extends React.Component {
  private input = React.createRef<HTMLInputElement>(); 
  componentDidMount() {
    if (this.input.current) {
      this.input.current.focus();
    }
  }
 
  render() {
    return (
      <form>
        <input ref={this.input} type="type" />
      </form>
    );
  }
}

如果我们运行这段代码,我们会看到焦点在渲染后被设置在输入上。😃