Home > Net >  setState of object using properties coming from a "ref"
setState of object using properties coming from a "ref"

Time:03-09

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)

Playground link

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.

  • Related