深入理解React中的ResizeObserver API - DhiWise

作者:API传播员 · 2026-01-07 · 阅读时间:5分钟

构建一个响应灵敏的 React 应用程序时,跟踪元素大小的变化是一个重要的环节。ResizeObserver API 提供了一种高效的方式,通过观察单个元素的大小变化,而不是依赖全局窗口的调整大小事件,从而提升性能。然而,在使用过程中,开发者可能会遇到一些常见警告。本文将深入探讨这些警告的原因及其解决方案。


什么是 React 的 ResizeObserver?

ResizeObserver API 允许 React 组件响应元素大小的变化。与传统的 window.onresize 事件不同,ResizeObserver 可以监视特定的组件或 DOM 元素。这在 React 中尤为重要,特别是用于动态布局管理、媒体缩放(如视频播放器)或复杂 UI 的调整。

在 React 组件中的典型实现步骤包括:

  • 使用 useRef 创建引用。
  • useEffect 钩子中观察目标元素。
  • 在组件卸载时清理观察者。

以下是一个简单的实现示例:

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

const ResizeObserverExample = () => {
  const elementRef = useRef(null);  useEffect(() => {
    const resizeObserver = new ResizeObserver((entries) => {
      entries.forEach((entry) => {
        console.log('Element size changed:', entry.contentRect);
      });
    });    if (elementRef.current) {
      resizeObserver.observe(elementRef.current);
    }    return () => {
      resizeObserver.disconnect();
    };
  }, []);  return 
观察此元素的大小变化
; };export default ResizeObserverExample;

警告:“ResizeObserver 循环已完成,但通知未送达”

当浏览器控制台中出现此警告时,意味着 ResizeObserver 已检测到大小变化,但在当前周期内未能处理所有通知。以下是可能导致此问题的几种情况:

  • 过多的调整大小事件:快速更新(如动画或过渡期间)可能让观察者不堪重负。
  • 第三方扩展干扰:例如,LastPass 等浏览器扩展可能通过注入元素或修改布局触发意外的调整大小事件。
  • 应用程序错误:组件状态更新或布局调整可能无意中触发新的调整大小事件,导致循环。
  • 框架生成的重复渲染:React 的重新渲染与动态布局计算结合时,可能引发重复的调整大小通知。

如何诊断 React 应用中的问题?

要找出警告的根本原因,可以采取以下步骤:

  1. 使用隐身模式测试:在禁用扩展的情况下运行应用程序,检查是否是第三方扩展导致了额外的通知。
  2. 检查调整大小处理程序:确保响应调整大小事件的更新不会导致递归变化。例如,避免调整大小事件直接触发另一次调整大小。
  3. 使用开发工具监控:通过 React DevTools 或浏览器开发工具监控组件的重新渲染,并检查是否存在意外的大小修改。
  4. 检查 UI 库或自定义钩子:如果使用了包含 ResizeObserver 的 UI 库或自定义钩子,查看是否存在已知问题或推荐配置。

处理测试和错误监控中的警告

在 Cypress 测试中忽略警告

如果在使用 Cypress 进行端到端测试时遇到此警告,可以通过以下代码段忽略它:

Cypress.on('uncaught:exception', (err) => {
  if (err.message.includes('ResizeObserver loop')) {
    return false; // 忽略 ResizeObserver 警告
  }
});

在 Sentry 中忽略警告

为了避免在 Sentry 中混淆错误报告,可以将警告添加到忽略列表中:

Sentry.init({
  ignoreErrors: ['ResizeObserver loop completed with undelivered notifications'],
});

修复 React 中的警告

以下是处理 ResizeObserver 警告的有效策略:

1. 不需要时断开 ResizeObserver

始终在 useEffect 的清理函数中断开 ResizeObserver,以防止内存泄漏和冗余观察。

useEffect(() => {
  const observer = new ResizeObserver(callback);
  observer.observe(element);

  return () => {
    observer.disconnect();
  };
}, []);

2. 限制 Resize 回调的频率

快速调整大小可能触发过多通知。可以使用去抖动或节流策略限制回调执行频率:

const debounce = (func, delay) => {
  let timeout;
  return (...args) => {
    clearTimeout(timeout);
    timeout = setTimeout(() => func(...args), delay);
  };
};

const resizeCallback = debounce(() => {
  console.log('调整大小事件');
}, 300);

3. 避免递归布局更改

在处理调整大小事件时,避免触发导致另一次调整大小的额外 DOM 更新。可以使用 window.requestAnimationFrame 延迟更改:

resizeObserver.observe(element);
resizeObserver.callback = () => {
  window.requestAnimationFrame(() => {
    // 延迟处理布局更新
  });
};

4. 限制观察的元素

避免将 ResizeObserver 附加到大量元素,仅观察需要动态调整的元素。


在 React 中使用 ResizeObserver 的最佳实践

为了充分利用 ResizeObserver,同时避免性能问题,请遵循以下最佳实践:

  • 谨慎使用 ResizeObserver:仅监视对组件渲染有直接影响的元素。
  • 优化回调函数:编写高效的回调函数,避免触发额外的布局重新计算。
  • 实施去抖动或节流:减少更新频率,防止观察者超负荷。
  • 确保正确清理:在 useEffect 中连接和断开观察者,避免内存泄漏。
  • 彻底测试:使用 React DevTools 和浏览器调试工具,定期检查应用在不同屏幕和设备上的行为。

总结

“ResizeObserver 循环已完成,但通知未送达” 警告通常表明布局调整可能导致性能问题。在 React 应用中,通过实施去抖动策略、正确清理观察者以及避免不必要的更新,可以有效解决此问题。

通过遵循本文提供的修复和最佳实践,开发者可以确保 React 组件在响应性和性能之间取得平衡,从而构建出更高效的应用程序。

原文链接: https://www.dhiwise.com/blog/design-converter/resolving-resizeobserver-loop-completed-with