在 Typescript 中使用 React Refs
介绍
对于绝大多数 React 组件,一切都可以使用声明式模型完成,该模型使用 props 与子组件通信以重新渲染。然而,在某些情况下,需要使用命令式编程模型并访问底层 DOM 元素。例如,设置元素的焦点、访问元素的实际尺寸或使用仅对 DOM 元素进行操作的非 React 第三方库。无论出于何种原因,这都可以使用 React refs来实现。
本指南将展示如何使用Typescript来使用强类型引用。我们将了解如何使用hooks API从功能组件中使用引用、从 16.3 及更高版本中的类组件中使用引用、从 16.3 之前版本中的类组件中使用引用以及将引用转发到其他组件。每个示例都将渲染一个宽度为 100% 的div ,获取对 div 元素的引用,并使用clientWidth属性将其实际宽度写入控制台。
请注意,无论使用refs的原因是什么,都应谨慎使用,并且应尽可能使用声明式模型。
功能组件
要在功能组件中使用 ref,我们需要使用useRef hook创建 ref :
const divRef = React.useRef<HTMLDivElement>(null);
此代码创建了一个RefObject实例,该实例可以接受HTMLDivElement类型的 ref ;RefObject有一个属性current,可以将其设置为null或HTMLDivElement实例。由于我们尚未渲染组件,因此 ref 被初始化为null。
当使用ref prop声明元素时,会设置 ref :
return <div ref={divRef} style={{ width: "100%" }} />;
如果使用除div之外的其他元素,Typescript 编译器将抛出错误,然后divRef.current将设置为div的底层 DOM 元素,并可在组件代码中访问。在此示例中,我们将在组件安装后使用 ref 将clientWidth写入控制台:
React.useEffect(() => {
if (divRef.current) {
console.log(`hookRef div width: ${divRef.current.clientWidth}`);
}
}, []);
此代码使用Effect hook并以空数组作为依赖项参数,以确保代码仅在组件挂载时执行。它只是测试 ref 是否已设置 - 如果省略if语句,Typescript 编译器将报告错误 - 如果已设置,则将其宽度写入控制台。
该组件的代码可以在这里找到。
类组件
使用类组件时,ref 仍然可用。在类中,可以将其创建为类字段:
divRef = React.createRef<HTMLDivElement>();
与上面的函数组件示例一样,这将this.divRef设置为一个RefObject ,该 RefObject 接受HTMLDivElement类型的 ref 。在这种情况下,ref 被初始化为null,而无需指定任何参数。
在render方法中,ref prop 的使用方式和前面的例子一样:
render() {
return <div ref={this.divRef} style={{ width: "100%" }} />;
}
现在可以使用this.divRef.current从类内部访问 DOM 元素,因此可以在组件安装时像这样使用它:
componentDidMount() {
if (this.divRef.current) {
console.log(`createRefRef div width: ${this.divRef.current.clientWidth}`);
}
}
与前面的示例一样,代码测试 ref 是否已设置,并将宽度写入控制台。
该组件的代码可以在这里找到。
引用回调
createRef函数是在 React 16.3 版中引入的。因此,在使用以前的版本时,需要使用不同的技术来访问 ref。在前面的示例中,ref prop 已设置为RefObject的实例,但也可以将其设置为接受 DOM 元素参数的回调方法。然后可以使用此回调将类字段设置为元素:
divRef: HTMLDivElement | null = null;
setDivRef = (element: HTMLDivElement) => {
this.divRef = element;
};
由于没有RefObject,类字段的类型为HTMLDivElement | null,这意味着它可以设置为null或HTMLDivElement并初始化为null。
然后在render方法中将ref prop 设置为这个回调:
render() {
return <div ref={this.setDivRef} style={{ width: "100%" }} />;
}
最后在componentDidMount中可以访问 ref:
componentDidMount() {
if (this.divRef) {
console.log(`callbackRef div width: ${this.divRef.clientWidth}`);
}
}
该组件的代码可以在这里找到。
转发 Refs
有时从父级 React 组件内部访问子级 React 组件内的 DOM 元素会很有用。为此,我们可以使用转发 refs。
要接受前向引用,可以使用接受两个参数(props 和 ref)的forwardRef函数创建子组件。然后可以在以相同方式声明元素时设置 ref,就像在组件内创建元素一样:
const Forward = React.forwardRef((props, ref: React.Ref<HTMLDivElement>) => (
<div ref={ref} style={{ width: "100%" }} />
));
与前面的例子不同,转发的 ref属于RefObject类型,而是属于Ref类型。
访问转发的 ref 与使用常规 ref 完全相同 - 创建 ref、设置ref prop,然后使用current属性访问它:
function ForwardRefRef() {
const divRef = React.useRef<HTMLDivElement>(null);
React.useEffect(() => {
if (divRef.current) {
console.log(`forwardRefRef div width: ${divRef.current.clientWidth}`);
}
});
return <Forward ref={divRef} />;
}
该组件的代码可以在这里找到。
结论
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~