I have an initial state object with coordinates x = 0 and y = 0
, which I want to update when the html element the ref is attached to gets rendered.
Typescript however is telling me that the properties I am trying to access in useEffect do not exist, with errors such as
Property 'offsetWidth' does not exist on type 'never'.ts(2339)
.
Property 'offsetHeight' does not exist on type 'never'.ts(2339)
How can I define what I want to set in the setState method?
const HierarchyScene = () => {
const [initialTreePosition, setInitialTreePosition] = useState({
x: 0,
y: 0
})
const hierarchyContainerRef = useRef(null)
useEffect(() => {
if (hierarchyContainerRef) {
setInitialTreePosition({
x: hierarchyContainerRef?.current?.offsetWidth || 0,
y: hierarchyContainerRef?.current?.offsetHeight || 0
})
}
}, [hierarchyContainerRef])
return (
<Box ref={hierarchyContainerRef}>
<Tree translate={initialTreePosition} />
</Box>
)
}
CodePudding user response:
Preface: Beware that even after solving the type problem, if things are resized, your component's tree position information could be incorrect. Ideally, avoid storing that information in state entirely, and use it from the ref every time you need it. Or even better, if possible, avoid needing it at all.
You have to tell TypeScript what the ref will reference, by providing the type argument. For instance, if you were going to use the ref
on a div
, it would be:
// **IF** it were going to be a `div`
const hierarchyContainerRef = useRef<HTMLDivElement>(null)
In your actual code, it's a Box
, which looks like it renders a div
so I assume it forwards the ref to the div
, but you may need something more specific to Material-UI. The fundamental thing is you have to say what the ref
will refer to.
Digging around in Material-UI, I can't see that Box
directly supports ref
despite this suggesting that it does. BoxProps
doesn't seem to have ref
on it. The Box
documentation lists children
, clone
, and component
and says "Any other properties supplied will be used by the style functions or spread to the root element." but the TypeScript type doesn't seem to support doing that.
You may have to suppress the error using ref
on Box
, but perhaps the Material-UI folks can help with using refs on their components.