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

在上一篇文章中,我们介绍了如何使用强类型的 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的例子,我们会看到焦点被设置为输入元素。
很好!😃