用TypeScript转发React Refs的实例

361 阅读2分钟

在这篇文章中,我们将介绍如何用TypeScript转发React refs:

Forwarding React Refs with TypeScript

上一篇文章中,我们介绍了如何使用强类型的 ref 来调用 React 组件中 HTML 元素上的方法。如果我们想访问一个不直接在React组件中的HTML元素--而是在一个子组件中的HTML元素,该怎么办。

让我们想象一下,我们已经创建了一个可重复使用的Search 组件,它包裹了一个input 元素,就像下面的例子:

function Search() {
  return <input type="search" />;
}

当消耗Search ,让我们想象一下,我们想在input 元素被加载到DOM后,将焦点设置到该元素。因此,我们尝试使用一个ref ,并将焦点设置到useEffect 中的input 元素,就像下面这样:

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

  React.useEffect(() => {
    if (input.current) {
      input.current.focus();
    }
  }, []);

  return <Search ref={input} />;
  // 💥 - Property 'ref' does not exist on type 'IntrinsicAttributes'
}

但这并不奏效,当我们在Search 组件上引用ref 时,会出现一个类型错误。😞

为了使其发挥作用,我们需要将ref 转发到App 组件。我们可以通过以下方式实现这一点 forwardRef从React中实现:

const Search = React.forwardRef((props, ref) => {
  return <input ref={ref} type="search" />;
});

我们将Search 组件包裹在forwardRef 函数中,该函数为我们做引用转发。

但这引发了一个类型错误,因为ref 被推断为unknown 的类型。😞

forwardRef 是一个通用函数,它的类型参数是Ref和props的类型:

const Component = React.forwardRef<RefType, PropsType>((props, ref) => {
  return someComponent;
});

这有点令人困惑,因为通用参数的排序(ref ,然后是props )与函数参数的排序(props ,然后是ref )相反。😕

总之,如果我们为ref ,添加通用参数,类型错误就解决了:

const Search = React.forwardRef<HTMLInputElement>((props, ref) => {
  return <input ref={ref} type="search" />;
});

注意,我们不需要传递props的通用参数,因为我们在这个组件中没有任何props。

🏃播放代码

如果你运行CodeSandbox的例子,我们会看到焦点被设置为输入元素。

很好!😃