【问题标题】:React inaccurately calculating the height of a div on first page load在第一页加载时反应不准确地计算 div 的高度
【发布时间】:2021-07-20 09:00:41
【问题描述】:

我正在寻找一种可靠的策略来计算其中包含许多孩子的父母的身高,无论孩子是图像、视频还是字体等。(想想投资组合内容)

可以在此处找到该问题的一个简单示例:

https://codesandbox.io/s/wrong-height-tkvcm?file=/src/useHeight.js:347-545


图像加载速度很慢,因此计算函数会过早触发。并且由此产生的高度计算完全关闭。

我尝试过的事情

  • 计算所有图像的比例,明确设置图像高度。这行得通,但是我仍然有视频、字体、慢速 API 也需要加载。所以这个策略感觉很坑爹。

  • 调整大小观察者。也无法可靠地等待内容加载。性能昂贵。还有这个issue

  • React setState/useEffect/array 依赖项。让我走得很远,但最终还是失败了,因为很难知道哪个状态会最后触发以更新高度计算。

  • 我尝试了 React 并发模式来尝试在计算开始之前预加载内容。对于非 API 的情况,这似乎有点过头了。我只需要担心本地图像和资产。

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

我确实认为使用 React 预加载内容是最好的方法,但我很想知道是否有其他人尝试解决在内部包含大量内容的大型容器上计算尺寸的问题?

更复杂的例子: https://codesandbox.io/s/stupefied-wilson-qzb1i?file=/src/components/CaseWrapper/index.js:756-836

【问题讨论】:

    标签: javascript html reactjs react-hooks


    【解决方案1】:

    大小差异可能是由于您使用的自定义字体所致。刷新页面时,您会注意到字体加载后的文本移动。

    尝试删除base.css中的所有@font-face,问题就会消失。

    或者,您可以在计算高度之前等待document.fonts.ready 回调。

    React.useEffect(() => {
      document.fonts.ready.then(function () {
        console.log('Fonts currently being used on the page are now loaded.');
        // Calculate height now
      });  
    }, []);
    

    【讨论】:

    • 感谢 Sohaib,绝对是管理布局抖动的有用方法,无论哪种方式我都会实现。我希望找到一个更简单的解决方案,可以预测加载的各种资产,而不仅仅是字体。还有更多 React-y。对于图像和视频,也许有类似的解决方案。 (我已经在使用 padding-bottom hack 来防止图像抛出布局)
    【解决方案2】:
    1. 要确保所有图像都已加载,您可以在该 HTML 元素上使用 onLoad 事件。

    2. handleLoad 完成后会将状态“已加载”设置为 true

    3. 然后您可以将'loaded' 状态传递给useHeight 并确保它在完成加载后计算元素

    // App.js
    ...
    
    
    return() (
      const [loaded, setLoaded] = useState(false);
      const height = useHeight(elementDOM, loaded); // 3.
    
      // 2.
      const handleLoad = () => {
        setLoaded(true);
      };
      ...
        <div ref={elementDOM} className="box" onLoad={handleLoad}> // 1.
        ..
        ..
        </div>
      ...
    );
    ...
    
    // useHeight.js
    ...
    function useHeight(elementRef, isLoaded) {
      const updateHeight = useCallback(() => {
        if (isLoaded && elementRef && elementRef.current) {
          const { height } = elementRef.current.getBoundingClientRect();
          setHeight(height);
        }
      }, [isLoaded, elementRef]);
    
      ...
      return height;
      ...
    }
    ...
    

    Forked sandbox

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-22
      • 2014-12-24
      • 1970-01-01
      • 1970-01-01
      • 2018-07-24
      • 2015-03-03
      • 1970-01-01
      相关资源
      最近更新 更多