react-hook icon indicating copy to clipboard operation
react-hook copied to clipboard

Reference change doesn't reflect in the entry

Open WilliamGusmanov opened this issue 2 years ago • 5 comments
trafficstars

Describe the bug When the chartRef changes. The entry still points to the original reference rather than being updated.

WilliamGusmanov avatar Apr 25 '23 01:04 WilliamGusmanov

Sorry, can you elaborate?

jaredLunde avatar Apr 27 '23 13:04 jaredLunde

Given the example:

import * as React from 'react'
import useResizeObserver from '@react-hook/resize-observer'

const useSize = (target) => {
  const [size, setSize] = React.useState()

  React.useLayoutEffect(() => {
    setSize(target.current.getBoundingClientRect())
  }, [target])

  // Where the magic happens
  useResizeObserver(target, (entry) => setSize(entry.contentRect))
  return size
}

const App = () => {
  const target = React.useRef(null)
  const size = useSize(target)
  const [useOther, setUseOther] = useState(false);
  return (
    <div>
    { !useOther &&
    <div id="1" ref={target}>
      {JSON.stringify({width: size.width, height: size.height}, null, 2)}
    </div>
    }
    { useOther && 
    <div id="2" ref={target}>
      {JSON.stringify({width: size.width, height: size.height}, null, 2)}
    </div>
    <button onClick={() => setUseOther(!useOther)} />
    }
   </div>
  )
}

useResizeObserver will observe changes to 'id 1' but when the button is clicked and the reference changes to 'id 2', the target.current will change its reference, but that change is not reflected in the useResizeObserver. It still reflects changes on 'id 1'.

WilliamGusmanov avatar Apr 27 '23 17:04 WilliamGusmanov

Would advise against doing what you're doing. Use a separate ref and useSize hook for each div instead

jaredLunde avatar Apr 27 '23 22:04 jaredLunde

Even when using a separate ref and useSize hook the newly rendered ref's useSize only seems to return 0, 0. Has anyone has success with this swap technique?

yoiang avatar Jun 30 '23 00:06 yoiang

I believe this issue has bit me too; my use case is simpler than that previously presented here, and I think it should be supported (currently it isn't supported). My component looks like this:

function App() {
   const [loading, setLoading] = useState(true);
   const target = useRef(null);
   const [width, height] = useSize(target);

   useEffect() {
      // call async function and eventually setLoading(false);
   }, []);

  return loading ? <></> : <div ref={target}/>;
}

So, the ref is not assigned on the first render because the respective div does not exist yet.

cc @laurolins

andreimatei avatar Mar 30 '24 23:03 andreimatei