Reactjs-使用React Hooks获取div /图像的高度

我想使用react钩子获取react功能组件中图像的高度。

我用下面的代码:

import React, { useRef, useEffect } from 'react'

const DepthChartContent = props => {
  const ref = useRef()

  useEffect(() => {
    if (ref && ref.current && ref.current.clientHeight) {
      console.log('called')
    }
    console.log('useEffect', {
      ref,
      current: ref.current,
      clientHeight: ref.current.clientHeight,
    })
  }, [])

  return (
    <img
      ref={ref}
      className="depth-reference-bar"
      src={DepthRuler}
      alt="no ruler found"
    />
  )
}

问题在于它返回的clientHeight为0,但是useEffect中的console.log具有正确的clientHeight,如下图所示。

ref-console-image

This means that ref && ref.current && ref.current.clientHeight is not defined when called but consoling in same useEffect is showing correct value for ref, current: ref.current but clientHeight: ref.current.clientHeight is ZERO.

Similarly, I can't use ....}, [ref && ref.current && ref.current.clientHeight] in useEffect because useEffect do not accept complex expression. If I defined a variable outside or inside useEffect as const clientHeight = (ref && ref.current && ref.current.clientHeight) || 0, no luck!

任何人都可以在这方面提供帮助。谢谢!

评论
  • 葬痴心
    葬痴心 回复

    useEffect callback happen immediately after render; the browser won't have had a chance to layout the elements yet. You're seeing the correct height later becaue of this feature of console.

    On most modern browsers, you should be able to fix this using a setTimeoout with the value 0. Or, alternately, two requestAnimationFrame callbacks (the first will happen just before the element is laid out, so not helpful; the second is afterward).

    例如:

    useEffect(() => {
      const cancelled = false;
      const getHeight = () => {
        const { current } = ref; // `ref` will never be falsy
        if (!current || !current.clientHeight) {
          if (!cancelled) {
            requestAnimationFrame(getHeight);
          }
        } else {
          // Use `current.clientHeight` here
        }
      };
      return () => {
          cancelled = true;
      };
    }, []);
    

    当然,高度可以根据随后发生的其他变化而变化...

  • DJHongKong
    DJHongKong 回复

    效果执行时最有可能尚未加载图像,因此图像的高度为0。稍后加载图像时,它将更新节点的属性,这就是您在控制台中看到的内容(因为您正在记录节点实例)。

    You can subscribe to the load event in your useEffect callback like this:

      useEffect(() => {
          ref.current.addEventListener('load', () => {
              console.log(ref.current.clientHeight);
          });
      }, [ref])