
React 的 useEffect 无法直接监听 window.innerWidth 或 window.innerHeight 的动态变化,因为它们不是 React 响应式状态或可变引用——将其写入依赖数组毫无意义,这些值在组件渲染时仅被静态读取一次。
react 的 `useeffect` 无法直接监听 `window.innerwidth` 或 `window.innerheight` 的动态变化,因为它们不是 react 响应式状态或可变引用——将其写入依赖数组毫无意义,这些值在组件渲染时仅被静态读取一次。
在 React 中,useEffect 的依赖数组(dependency array)只对 JavaScript 变量的引用或值变化 做响应,而 window.innerWidth 和 window.innerHeight 是只读属性,每次访问都返回当前值,但它们本身不是可被“监听”的响应式变量,也不会触发重渲染或 effect 重新执行。
你原始代码的问题在于:
useEffect(() => {
setcurrentWindowHeight(window.innerHeight);
setcurrentWindowWidth(window.innerWidth);
}, [window.innerHeight, window.innerWidth]); // ❌ 错误用法
这段代码在首次渲染时会将 window.innerHeight 和 window.innerWidth 的瞬时数值(如 768 和 1280)作为依赖项存入数组。但这两个值是原始数字类型(primitives),useEffect 在后续比较时,实际比对的是上一次渲染时捕获的数字值 —— 而不是“持续监控窗口对象”。因此,即使窗口大小改变,window.innerHeight 下次再读仍是新值,但 useEffect 并不会主动“重新读取并比较”它;它只会在依赖项发生浅层变化时才触发,而这里的依赖项根本不会自动更新 —— 它们不是 state、ref 或 props,只是普通全局属性访问。
✅ 正确做法是:使用事件驱动机制,监听浏览器原生的 "resize" 事件,并在事件回调中更新状态:
import { useState, useEffect } from 'react';
function WindowSizeDisplay() {
const [width, setWidth] = useState(window.innerWidth);
const [height, setHeight] = useState(window.innerHeight);
useEffect(() => {
const handleResize = () => {
setWidth(window.innerWidth);
setHeight(window.innerHeight);
};
// 注册 resize 事件监听器
window.addEventListener('resize', handleResize);
// 清理:组件卸载时移除监听器(防止内存泄漏)
return () => {
window.removeEventListener('resize', handleResize);
};
}, []); // 空依赖数组 → 仅在挂载/卸载时执行一次
return (
<h1>— {width} × {height} —</h1>
);
}
export default WindowSizeDisplay;
? 关键要点总结:
- useEffect 的依赖项必须是组件作用域内可追踪的变量(如 state、props、ref.current 或由它们派生的稳定值),不能是随时变化却无引用绑定的全局属性;
- window.innerWidth/Height 是“快照值”,不是响应式信号,需靠事件(如 resize)驱动更新;
- 必须在 useEffect 清理函数中移除事件监听器,否则会导致:
- 内存泄漏(监听器持续驻留);
- 多次挂载后重复绑定(如父组件条件渲染导致子组件反复挂载);
- 若需更高性能(避免频繁触发 setState),可添加防抖(debounce)逻辑,例如使用 lodash.debounce 或自定义 hook 封装。
? 进阶建议:可封装为自定义 Hook 提升复用性:
function useWindowSize() {
const [size, setSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
useEffect(() => {
const handleResize = () => {
setSize({
width: window.innerWidth,
height: window.innerHeight,
});
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return size;
}
// 使用方式:
// const { width, height } = useWindowSize();
这样既符合 React 的数据流设计哲学,也确保了行为可预测、资源安全、代码简洁。











