Detect element reference height change

Viewed 2899

Is it possible to detect when an element reference changes it's height? I tried using the following, but when the height of the element changes for whatever reason, the change is not detected. (Please consider that this must also work in IE11)

useEffect(() => {
  // detect change in reference height
}, [elementRef])
4 Answers

I think you can use elementRef.current.clientHeight in useEffect dependencies in order to listen to tag's height.

I test with this case and it worked.

function App() {
  const tag = useRef();
  const [height, setHeight] = useState(10);
  useEffect(() => {
    console.log("updated", tag?.current?.clientHeight);
  }, [tag?.current?.clientHeight]);

  useEffect(() => {
    setInterval(() => {
      setHeight((height) => height + 10);
      console.log(height, tag.current.clientHeight);
    }, 2000);
  }, []);

  return (
    <div className="App" ref={tag}>
      <div style={{ height: height, backgroundColor: "green" }}></div>
    </div>
  );
}

Here is the codesandbox https://codesandbox.io/embed/reactjs-playground-forked-b8j5n?fontsize=14&hidenavigation=1&theme=dark

The most efficient way is to use a resize observer.

You can set it up in a useEffect, and clear it when the component unmounts.

You could just use window.

My example below is optimised with a cleanup removeEventListener function should the component unmount.

const BoxAndHeight = () => {
  const ref = React.useRef(null);
  const [height, setHeight] = React.useState(0);

  const onResize = React.useCallback(() => {
    if (ref.current) setHeight(ref.current.clientHeight);
  }, []);

  React.useEffect(() => {
    window.addEventListener("resize", onResize);
    onResize();
    return () => {
      window.removeEventListener("resize", onResize);
    };
  }, []);

  return (
    <div ref={ref} style={style}>
      <h1>My height: {height}</h1>
      <p>
        {dummyContent}
      </p>
    </div>
  );
}

// Render it
ReactDOM.createRoot(
    document.getElementById("root")
).render(<BoxAndHeight />);

const style = {
  border: "2px solid #ccc",
  padding: "10px",
  backgroundColor: "#eee"
};
const dummyContent = "Lorem ipsum dolor sit, amet consectetur adipisicing elit. Distinctio, fugiat. Ex in neque velit perspiciatis recusandae, deleniti illum error ea distinctio obcaecati nisi deserunt ab unde corporis quas magnam quo cupiditate dolor dicta? Eos nostrum delectus suscipit! Hic corrupti, assumenda quo modi rem aperiam voluptas explicabo alias fuga error nulla. Eos tenetur voluptas repellat. Tempore, ab harum. Recusandae impedit adipisci soluta officia sunt quis voluptas, quae ea! Eveniet vero incidunt enim quod, voluptate fugiat maxime deserunt et laudantium quidem, ducimus sunt ratione voluptatem libero neque accusamus praesentium fugit doloremque est nisi excepturi. Quo inventore est soluta culpa quos? Minus, laudantium!";
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

Possible solution is to use a React Refs. Try this example as reference:

export default function Home() {
  const divRef = createRef()
  // ...
  return (
    <div style={{ height: '100vh', width: '100vw' }}>
      <div
        ref={divRef} // ...
      ></div>
    </div>
  )
}

Detailed code here.

Related