【react实战】如何实现监听窗口大小变化

在日常开发场景中,监听窗口变化是一个比较常见又很重要的业务功能,其实实现起来也很简单,今天就来记录一下具体的实现以及注意事项。

实现思路

在 React 中,可以通过监听 window 的 resize 事件来检测可视区域(viewport)的宽度变化。

其中实现的关键为:

  • window.innerWidth:获取浏览器可视区域的宽度
  • window 的 resize 事件:监听窗口大小的变化,但要注意防抖,避免触发性能问题。虽然 useEffect 只执行两次,但它注册的 resize 事件回调会在每次窗口变化时触发,而这个触发频率可能极高
  • 在组件销毁时正确清理监听器,移除 resize 事件监听,避免内存泄漏。

具体实现

js 复制代码
import React, { useEffect, useState } from 'react';

export default function ViewportWidthTracker() {
  const [width, setWidth] = useState(window.innerWidth);

  useEffect(() => {
  // 监听窗口大小变化
  let timeoutId = null;
  const handleResize = () => {
    // 每次触发 resize 时清除之前的定时器
    clearTimeout(timeoutId);
    // 设置新的定时器,延迟 150ms 执行
    timeoutId = setTimeout(() => {
      setSize({ width: window.innerWidth, height: window.innerHeight });
    }, 150);
  };

    window.addEventListener('resize', handleResize);

    // 清理监听器
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []); // 空依赖数组确保只在组件挂载和卸载时运行

  return (
    <div>
      <h1>当前可视区域宽度: {width}px</h1>
    </div>
  );
}

注意事项

  1. SSR 环境问题:在服务端渲染(如 Next.js)中,window 对象不存在。可通过条件判断避免错误
js 复制代码
useEffect(() => {
 if (typeof window === 'undefined') return;
 // 监听逻辑
}, []);
  1. 组件卸载时清理:必须在 componentWillUnmount 或 useEffect 返回的清理函数中移除事件监听,防止内存泄漏。

封装自定义 hook

这个场景比较常见,可以封装为自己的 hook,方便后续调用。

js 复制代码
import { useState, useEffect } from 'react';

function useWindowSize() {
  const [size, setSize] = useState({ width: 0, height: 0 });

  useEffect(() => {
  	// 监听窗口大小变化
  let timeoutId = null;
  const updateSize = () => {
    // 每次触发 resize 时清除之前的定时器
    clearTimeout(timeoutId);
    // 设置新的定时器,延迟 150ms 执行
    timeoutId = setTimeout(() => {
      setSize({ width: window.innerWidth, height: window.innerHeight });
    }, 150);
  };
    
    window.addEventListener('resize', updateSize);
    updateSize();
    
    return () => window.removeEventListener('resize', updateSize);
  }, []);

  return size;
}

// 使用自定义 Hook
function MyComponent() {
  const size = useWindowSize();
  
  return (
    <div>
      当前窗口: {size.width} x {size.height}
    </div>
  );
}
相关推荐
kk晏然13 分钟前
TypeScript 错误类型检查,前端ts错误指南
前端·react native·typescript·react
纆兰23 分钟前
汇款单的完成
前端·javascript·html
酷酷的鱼28 分钟前
2026 React Native新架构核心:JSI底层原理与老架构深度对比
react native·react.js·架构
Lsx_41 分钟前
案例+图解带你遨游 Canvas 2D绘图 Fabric.js🔥🔥(5W+字)
前端·javascript·canvas
2501_944521001 小时前
rn_for_openharmony商城项目app实战-主题设置实现
javascript·数据库·react native·react.js·ecmascript
m0_471199631 小时前
【场景】如何快速接手一个前端项目
前端·vue.js·react.js
榴莲CC1 小时前
抗干扰LED数显屏驱动VK1624 数码管显示芯片 3线串行接口
前端
lili-felicity1 小时前
React Native for Harmony 个人消息列表最新消息置顶实现(多维度权重统计)
javascript·react native·react.js
Tigger2 小时前
用 Vue 3 做了一套年会抽奖工具,顺便踩了些坑
前端·javascript·vue.js
天天扭码2 小时前
一文搞懂——React 19到底更新了什么
前端·react.js·前端框架