I'm using useRef to reference a div element and storing getBoundingClientRect(). Upon using it, I get a TypeScript error of Property 'height' does not exist on type 'string'. How do I address this error?
const divRef = useRef(null);
const [divSize, setDivSize] = useState("0");
setDivSize(divRef.current.getBoundingClientRect());
console.log(divSize.height); // getting TS error: Property 'height' does not exist on type 'string'.
return (
<Content ref={divRef}>
{content}
</Content>
)
CodePudding user response:
Unconditionally calling a setState function at the top level of any component is always an error, because it initiates the reconciliation algorithm (infinitely). Here is a note from the React documentation (which needs to be updated for functional components):
You may call
setState()immediately incomponentDidUpdate()but note that it must be wrapped in a condition like in the example above, or you’ll cause an infinite loop.↳ https://reactjs.org/docs/react-component.html#componentdidupdate
To fix this, wrap the setState call in the effect hook:
const divRef = useRef<HTMLDivElement>(null);
const [divSize, setDivSize] = useState(0);
useEffect(() => {
if (!divRef.current) return;
const rect = divRef.current.getBoundingClientRect();
setDivSize(rect);
console.log(rect.height);
});
return (
<Content ref={divRef}>
{content}
</Content>
)
Also, you can't use the ref prop on a functional component.
CodePudding user response:
You can use a generic type with useRef to something that has getBoundingClientRect as a valid method, such as HTMLElement or HTMLDivElement:
const divRef = useRef<HTMLDivElement>(null);
That should properly allow to access height of result of getBoundingClientRect().
This is purely a solution for typing. The answer by jsejcksn help explain how to handle falsy/undefined ref in an effective way.
