⚛️ 揭秘 React 的类型:Ref 类型
在 ReactJS 中使用 TypeScript 时,在函数式组件中使用 ref 需要格外小心,以确保类型安全。本文将探讨基于 TypeScript 的函数式组件中最常用、最相关的 ref 类型。
1️⃣React.RefObject
类型React.RefObject
是函数式组件中处理引用的最常用方式。当你使用钩子创建引用useRef
并想要访问其当前值时,会用到它。引用容器为只读容器,其current
属性无法被修改。
下面是一个使用示例React.RefObject
:
import { useRef } from 'react';
export const MyComponent = () => {
const inputRef = useRef<HTMLInputElement>(null);
const handleClick = () => {
inputRef.current?.focus();
};
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={handleClick}>Focus Input</button>
</div>
);
};
inputRef
在这个例子中,我们使用钩子创建了一个名为的 ref useRef
,并将类型指定为HTMLInputElement
。
请注意,在使用 时useRef
,如果初始传递的值是null
,TypeScript 会自动将其理解为React.RefObject
。如果您希望它是React.MutableRefObject
并且初始值也是null
,那么简单的技巧就是将其定义为:
const inputRef = useRef<HTMLInputElement | null>(null);
2️⃣React.MutableRefObject
该React.MutableRefObject
类型与 类似React.RefObject
,但它允许current
引用的属性可变。这在需要直接更新引用值而不触发重新渲染的场景中非常有用。
下面是一个使用示例React.MutableRefObject
:
import { useRef } from 'react';
export const MyComponent = () => {
const counterRef = useRef<number>(0);
const handleClick = () => {
counterRef.current++;
console.log('Counter value:', counterRef.current++);
};
return (
<div>
<button onClick={handleClick}>Increment Counter</button>
</div>
);
};
3️⃣React.RefCallback
React.RefCallback
当你需要在特定时间点访问 DOM 元素或 React 组件时(例如组件挂载或卸载时),会用到该类型。当你使用需要直接访问 DOM 的第三方库,或者需要执行复杂的 DOM 操作,或者需要管理refs 列表时,这会特别有用。其类型定义如下:
type RefCallback<T> = (instance: T | null) => void;
下面是一个用于React.RefCallback
测量元素大小并相应更新组件状态的示例。这在需要实现响应式布局或动态 UI 元素的场景中非常有用。
import { useState, useCallback } from 'react';
export const MyComponent = () => {
const [elementSize, setElementSize] = useState<{ width: number; height: number }>({
width: 0,
height: 0,
});
const handleElementRef: React.RefCallback<HTMLDivElement> = useCallback((element) => {
if (!element) return;
const { offsetWidth, offsetHeight } = element;
setElementSize({ width: offsetWidth, height: offsetHeight });
}, []);
return (
<div ref={handleElementRef}>
<p>Element size: {elementSize.width} x {elementSize.height}</p>
</div>
);
};
4️⃣React.Ref
React.Ref
本质上是 React refs 所有可能形状的联合类型。你可以理解为:
type Ref<T> = RefCallBack<T> | RefObject<T> | null;
5️⃣React.ForwardedRef
当你需要将 ref 从父组件转发到子组件时,会用到该React.ForwardedRef
类型。当你使用可复用组件并需要访问底层 DOM 元素或 React 组件时,或者在子组件中使用 ref 创建自定义 ref 对象时,这尤其有用useImperativeHandle
。
下面是一个使用示例React.ForwardedRef
:
import { forwardRef, Ref } from 'react';
interface InputProps {
value: string;
onChange: (value: string) => void;
}
const InputBase = ({ value, onChange }: InputProps, ref: React.ForwardedRef<HTMLInputElement>) => {
return (
<input
type="text"
value={value}
onChange={(e) => onChange(e.target.value)}
ref={ref}
/>
);
});
export const Input = forwardRef(InputBase);
在这个例子中,我们使用forwardRef
函数创建一个 ref-forwarding 组件,它允许父组件访问底层input
元素。
6️⃣React.LegacyRef
React.LegacyRef
当你需要以兼容旧版 React 的方式使用 ref 时,可以使用此类型。此类型主要用于基于类的组件,这类组件在现代 React 开发中并不常见。
值得注意的是,ref
React 中每个原始 HTML 元素的属性目前都具有 类型React.LegacyRef<HTMLElementType>
。这意味着,如果你正在使用一个div
元素,那么该属性的类型ref
很可能是React.LegacyRef<HTMLDivElement>
。
实际上,您在 React 项目中根本不必关心这种类型。
🏁 结论
在本文中,我们探讨了 React 中最常用的 ref 类型,包括React.RefObject
、React.MutableRefObject
、React.RefCallback
、React.Ref
、React.ForwardedRef
和React.LegacyRef
。了解这些类型后,您将能够更自信地使用 TypeScript 编写 React 项目。敬请关注更多关于 React 和 TypeScript 的文章,我们将深入探讨构建健壮且可扩展应用程序的最新功能和最佳实践。
如果您认为这是一篇好文章,那么您可能也会发现我之前的文章很有用:
如果您对使用 ReactJS 进行前端开发和 Web 开发感兴趣,请关注我并查看下面个人资料中我的文章。
鏂囩珷鏉ユ簮锛�https://dev.to/itswillt/demystifying-reacts-types-ref-types-28fj