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

React中状态变更未在resize回调中生效,动态调整块宽度遇问题

React窗口resize时动态调整区块宽度的问题修复

问题根源

你的代码存在三个核心问题:

  1. 闭包陷阱:useEffect依赖为空数组,导致onResize函数捕获的myWidth始终是初始值200,状态更新后回调无法获取最新值,判断逻辑彻底失效。
  2. 无防抖处理:resize事件触发频率极高,窗口每变化一个像素就会执行一次回调,导致控制台频繁打印。
  3. 未清理事件监听:组件卸载时没有移除resize监听,可能引发内存泄漏。

修正后的代码

function X({ title }) {
  const [myWidth, setMyWidth] = React.useState(200);
  // 记录上一次的窗口阈值状态,避免重复触发调整逻辑
  const isOverThreshold = React.useRef(false);

  // 封装防抖的resize回调,减少触发频率
  const debouncedResize = React.useCallback(
    React.useMemo(() => {
      let timeoutId;
      return () => {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => {
          const currentOver = window.innerWidth > 1000;
          // 仅当阈值状态发生变化时,才执行宽度调整
          if (currentOver !== isOverThreshold.current) {
            isOverThreshold.current = currentOver;
            if (currentOver) {
              console.log(`Make Bigger:`, myWidth);
              setMyWidth(400);
            } else {
              console.log(`Make Smaller:`, myWidth);
              setMyWidth(200);
            }
          }
        }, 100); // 100ms防抖间隔,可根据需求调整
      };
    }, [myWidth]),
    [myWidth]
  );

  React.useEffect(() => {
    window.addEventListener('resize', debouncedResize);
    // 组件卸载时清理事件监听,避免内存泄漏
    return () => window.removeEventListener('resize', debouncedResize);
  }, [debouncedResize]);

  // 初始渲染时主动检查窗口宽度,确保初始状态匹配当前屏幕
  React.useEffect(() => {
    const initialOver = window.innerWidth > 1000;
    isOverThreshold.current = initialOver;
    if (initialOver) {
      setMyWidth(400);
    }
  }, []);

  return (
    <div>
      <div
        style={{
          backgroundColor: 'red',
          width: myWidth,
          height: 100,
        }}
      >
        Hello
      </div>
    </div>
  );
}

const el = document.querySelector("#root");
ReactDOM.render(<X title='Example Component' />, el);

关键改进说明

  • 闭包问题解决:通过useCallback和useMemo确保回调能获取最新的myWidth状态,同时用useRef独立记录阈值状态,避免依赖组件状态做重复判断。
  • 防抖优化:添加100ms延迟,只有窗口停止调整后才执行逻辑,彻底解决频繁触发的问题。
  • 内存泄漏预防:在useEffect的返回函数中移除resize监听,组件卸载时自动清理。
  • 初始状态校正:组件挂载时主动检查窗口宽度,确保初始渲染的区块尺寸符合当前屏幕阈值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 17:24:17