现代react中有两种 refs:ref 对象和 ref 回调。Ref 对象是由useRef(或在类组件中createRef)创建的:它是一个具有current属性的对象。在typescript中,这些有 type RefObject<T>, whereT是任何值current。
Ref 回调是另一种选择,某些高级情况需要它。您将一个函数传递给元素,该函数将在实例创建或销毁时回调。这些有类型(instance: T) => void。
将 ref 对象和 ref 回调组合成一个类型的简写是Ref<T>,看起来这就是您的代码所期望的。由于您尚未展示该代码,因此我必须对其外观进行一些有根据的猜测。假设您有一个接受 ref 作为props的组件(也许这样它就可以将其交给其内部组件之一):
interface ExampleProps {
buttonRef: Ref<HTMLButtonElement>
}
const Example: FC<ExampleProps> = ({ buttonRef }) => {
return (
<div>
<button ref={buttonRef}>Hello</button>
<div>
)
}
由于我已将 prop 定义为 Ref,因此它可以传入 ref 对象或 ref 回调。在这种情况下这很好,因为除了将它传递给按钮之外,我没有对它做任何事情。但是如果我尝试编写一些代码来与之交互,我不能假设它是一个对象或一个函数。
如果我需要这样做,也许我可以限制props,这样它只需要 ref 对象,然后我可以假设它会有.current
interface ExampleProps {
buttonRef: RefObject<HTMLButtonElement>
}
const Example: FC<ExampleProps> = ({ buttonRef }) => {
useEffect(() => {
console.log(buttonRef.current);
});
return (
<div>
<button ref={buttonRef}>Hello</button>
<div>
)
}
但也许我不想限制我的组件的使用方式,但我仍然需要能够以某种方式与 ref 交互。在这种情况下,我可能需要自己创建一个回调引用,然后向它添加逻辑来处理我对引用的使用和props对引用的使用:
interface ExampleProps {
buttonRef: Ref<HTMLButtonElement>
}
const Example: FC<ExampleProps> = ({ buttonRef }) => {
const myRef = useRef<HTMLButtonElement>(null);
useEffect(() => {
console.log(myRef.current);
});
return (
<div>
<button ref={(element) => {
(myRef as MutableRefObject<HTMLButtonElement>).current = element;
if (typeof buttonRef === 'function') {
buttonRef(element);
} else {
buttonRef.current = element;
}
}}>Hello</button>
<div>
)
}
的类型断言as MutableRefObject<HTMLButtonElement>是必需的,因为它myRef被标记为不可变的。这种类型反映了只有 react 才能修改.current属性的事实。这对正常用例来说很好,但是由于我们从 react 接管了这个责任,因此可以更改该值。