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

为何React组件中useEffect添加又移除监听仍能更新窗口尺寸?

问题解释

这段代码里的useEffect没有传入第二个依赖参数,这意味着它会在组件每一次渲染完成后都执行——包括初始渲染,以及每次状态更新后的重新渲染,并不是只执行一次。

具体执行流程如下:

  • 组件首次渲染:执行useEffect,给window添加resize事件监听,同时返回一个清理函数(这个清理函数不会立刻执行,要等到组件卸载或者下一次useEffect执行前才会触发)。
  • 调整浏览器窗口时,resize事件触发onResize函数,调用setWindowWidth和setWindowHeight更新状态,状态变化会触发组件重新渲染。
  • 组件重新渲染时,会先执行上一次useEffect返回的清理函数(移除之前绑定的onResize监听),然后再执行新的useEffect,给window绑定新的onResize监听(每次渲染生成的onResize是新的函数实例,但不影响事件触发)。
  • 所以每次窗口调整触发事件后,都会更新状态、触发重渲染、重新绑定监听,以此循环,组件就能持续显示最新的窗口尺寸。

不过这种写法存在性能问题:每次组件渲染都要解绑再绑定事件监听,而且每次onResize都是新的函数实例。建议优化写法,给useEffect加上空依赖数组[],让它只在组件挂载时绑定一次监听,同时用useCallback包裹onResize避免不必要的函数创建,优化后的代码示例:

import React, { useState, useEffect, useCallback } from 'react';

const WindowSize = () => {
  const [windowWidth, setWindowWidth] = useState(window.innerWidth);
  const [windowHeight, setWindowHeight] = useState(window.innerHeight);

  const onResize = useCallback(() => {
    console.log("resize detected");
    setWindowWidth(window.innerWidth);
    setWindowHeight(window.innerHeight);
  }, []);
  
  useEffect(() => {
    window.addEventListener('resize', onResize);
    return () => {
      window.removeEventListener('resize', onResize);
    }
  }, [onResize])

  return (
    <div>
      <p>Width: {windowWidth}</p>
      <p>Height: {windowHeight}</p>
    </div>
  );
};

export default WindowSize;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 02:34:57