There are two kinds of refs in modern react: ref objects, and ref callbacks. Ref objects are what's created by useRef
(or in class components, createRef
): it's an object with a current
property. In typescript, these have the type RefObject<T>
, where T
is whatever value(s) will be on current
.
Ref callbacks are another option, which are needed for some advanced cases. You pass a function into the element, and the function will be called back when the instance is created or destroyed. These have the type (instance: T) => void
.
A shorthand which combines both the ref object and the ref callback into a single type is Ref<T>
, and it looks like that's what your code expects. Since you haven't shown that code, I'll have to make some educated guesses about what it looks like. Suppose you have a component which accepts a ref as a prop (perhaps so it can then hand it off to one of its internal components):
interface ExampleProps {
buttonRef: Ref<HTMLButtonElement>
}
const Example: FC<ExampleProps> = ({ buttonRef }) => {
return (
<div>
<button ref={buttonRef}>Hello</button>
<div>
)
}
Since I've defined the prop to be a Ref, it can be passed in either a ref object, or a ref callback. That's fine in this case, since I'm not doing anything with it except passing it on to the button. But if I try to write some code to interact with it, I can't assume it to be an object or a function.
If I need to do this, perhaps I could restrict the prop so it only takes ref objects, and then I can assume it will have .current
interface ExampleProps {
buttonRef: RefObject<HTMLButtonElement>
}
const Example: FC<ExampleProps> = ({ buttonRef }) => {
useEffect(() => {
console.log(buttonRef.current);
});
return (
<div>
<button ref={buttonRef}>Hello</button>
<div>
)
}
But maybe I don't want to restrict the way my component can be used, and yet I still need to be able to interact with the ref. In that case, I'll need to make a callback ref of my own, and then add logic to it to handle both my use of the ref, and the prop's use of the ref:
interface ExampleProps {
buttonRef: Ref<HTMLButtonElement>;
}
const Example: FC<ExampleProps> = ({ buttonRef }) => {
const myRef = useRef<HTMLButtonElement | null>(null);
useEffect(() => {
console.log(myRef.current);
});
return (
<div>
<button
ref={(element) => {
myRef.current = element;
if (typeof buttonRef === "function") {
buttonRef(element);
} else {
buttonRef.current = element;
}
}}
>
Hello
</button>
</div>
);
};
const cardRef = useRef<HTMLDivElement>(null);
– Duckyconst ref: Ref<HtmlDivElement> = cardRef
? Or pass it as a prop to a component which expects aRef<HtmlDivElement>
? – Had