You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何复用React中获取容器动态尺寸的代码?

动态获取容器尺寸的React代码复用方案

问题场景

我正在学习React,需要实现多个依赖容器尺寸的响应式组件。当前单个组件的实现代码如下:

import React, { useEffect, useState, useRef } from "react";

const ComponentOne = () => {
  const refContainer = useRef();
  const [dimensions, setDimensions] = useState({ width: 0, height: 0 });

  const handleSize = () => {
    setDimensions({
      width: refContainer.current.offsetWidth,
      height: refContainer.current.offsetHeight,
    });
  };

  /* Run first time */
  useEffect(() => {
    handleSize();
  }, []);

  /* Run on resize */
  useEffect(() => {
    window.addEventListener("resize", handleSize);
  }, []);

  /* Some useful code which depends on those dimensions here
    .....
    */

  return (
    <>
      <div ref={refContainer}>Something produced by that useful code</div>
    </>
  );
};

export default ComponentOne;

现在需要创建5个类似组件,想封装工具函数/模块,传入容器引用返回尺寸。尝试过HOC,但无法处理ref的传递和使用。同时发现第三方库react-cool-dimensions有简洁的实现方式:

const { observe, width, height } = useDimensions();

只需设置ref={observe},加载和resize事件都在内部处理。

解决方案

1. 自定义Hook封装

既然HOC在ref处理上有局限,自定义Hook是更合适的复用方式,完全契合React的Hook复用逻辑,且能轻松处理ref和尺寸监听:

// useContainerDimensions.js
import { useState, useCallback } from "react";

export const useContainerDimensions = () => {
  const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
  const ref = useCallback(node => {
    if (node) {
      const updateDimensions = () => {
        setDimensions({
          width: node.offsetWidth,
          height: node.offsetHeight
        });
      };
      // 初始化获取尺寸
      updateDimensions();
      // 监听窗口resize
      window.addEventListener("resize", updateDimensions);
      // 组件卸载时清理监听
      return () => {
        window.removeEventListener("resize", updateDimensions);
      };
    }
  }, []);

  return { ref, ...dimensions };
};

使用示例:

import { useContainerDimensions } from "./useContainerDimensions";

const ComponentOne = () => {
  const { ref, width, height } = useContainerDimensions();

  /* 依赖width/height的业务代码 */

  return (
    <div ref={ref}>
      当前容器尺寸:宽{width}px,高{height}px
    </div>
  );
};

这个Hook的优势:

  • 用useCallback创建ref回调,避免不必要的重渲染
  • 自动处理初始化尺寸获取和resize监听
  • 组件卸载时自动移除监听,防止内存泄漏
  • 直接返回ref和尺寸数据,使用简洁

2. 使用第三方库react-cool-dimensions

如果不想自己维护监听逻辑,react-cool-dimensions是成熟的选择,它不仅处理窗口resize,还支持容器自身尺寸变化(比如子元素撑开容器)、防抖节流等高级功能。

基础使用方式:

import { useDimensions } from "react-cool-dimensions";

const ComponentTwo = () => {
  const { observe, width, height } = useDimensions({
    // 可选配置:防抖时间(单位ms)
    debounce: 100
  });

  return (
    <div ref={observe}>
      容器宽:{width}px,高:{height}px
    </div>
  );
};

这个库的核心优势:

  • 开箱即用,无需手写监听逻辑
  • 支持容器自身尺寸变化的监听(不止窗口resize)
  • 内置防抖节流,优化性能

内容的提问来源于stack exchange,提问作者Alex Bachurin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 01:27:06