React: How can I watch for property changes of my UseRef variable (UseEffect doesn't work)

Viewed 1047

I want to position a div as fixed and calculate top & left values depending on a reference

I thought about using UseEffect with UseRef and it worked for the initial rendering but doesn't update when any property of the reference changes e.g. due to scrolling.

How can I watch for changes of my reference? Thx!

Here is my code:

  const triggerRef = useRef(null)
  const [popupStyles, setPopupStyles] = useState({})

  useEffect(() => {
    if (triggerRef.current) {
      setPopupStyles({
        width: `${triggerRef.current.offsetWidth}px`,
        left: `${triggerRef.current.offsetLeft}px`,
        top: `${triggerRef.current.offsetTop + triggerRef.current.offsetHeight}px`
      })
    }
  }, [triggerRef])

  return (
    <>
      <button ref={triggerRef} onClick={() => setState(!state)}>
        Open Popup
      </button>

      <div className="z-50 fixed" ref={popupRef}>
        {state && (    
            <div style={popupStyles} className="form-input opacity-75">
              Popup content
            </div>
        )}
      </div>
    </>
  )
2 Answers

It works with useEffect, but you need to watch the ref's current value:

  const containerRef = useRef();
  const { current } = containerRef;

  useEffect(setLinksData, [current]);

return (
    <div ref={containerRef}>
      // your child elements...
    </div>
)

Watch the ref element via scroll on page, set the state of the current value and watch the state

Example:

Init state & ref

  const [offset, setOffset] = useState(null);

  const myRef = useRef(null);

Watch ref element on scroll

useEffect(() => {
  window.onscroll = () => {
    const refHtmlElement = myRef?.current;

    if (refHtmlElement) {
      setOffset(refHtmlElement.getBoundingClientRect().top);
    }
  };
}, [myRef]);

Watch updated state

useEffect(() => {
  console.log('!!! offset: ', offset);
}, [offset]);

HTML

<div ref={myRef}>MyRef</div>
Related