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

使用React Hooks时resize触发后dimensions与clipPath不更新如何解决?

问题根源&修复方案

你最初版本的问题是典型的React闭包陷阱:你给useEffect配置的依赖是空数组,导致回调函数里引用的dimensions永远是组件首次渲染时的初始值,哪怕你调用setDimensions更新了状态,闭包拿到的还是旧值。同时你把sidebar写成普通函数每次调用都生成新的状态和事件监听器,逻辑设计也不合理。

你更新后的代码还有几个问题需要修复:

  1. 自定义HookgetDimensions的事件监听器无法正常卸载:你addEventListener和removeEventListener传入的是两个不同的匿名函数,引用地址不一致,导致卸载时根本删不掉之前绑定的监听器,需要把回调函数提出来单独定义。
  2. 代码里MobileNavWrapper组件传的custom={height}是错误的:你前面从getDimensions解构出来的变量是windowHeight,如果没有额外定义height变量的话这里传的就是undefined,值根本不对。
  3. Framer Motion的variants默认只在动画状态切换时重新计算,你窗口resize的时候如果菜单的开/关状态没有变化,它不会重新计算clipPath,给MobileNavBackground加一个和窗口高度绑定的key,强制它在高度变化时重新渲染,就能拿到最新的高度值计算样式。

优化后代码

首先修改getDimensions,修复事件卸载问题并添加防抖优化性能:

// getDimensions.ts
import { useState, useEffect } from 'react';

function debounce(func: Function, wait: number) {
  let timeout: NodeJS.Timeout;
  return (...args: any[]) => {
    clearTimeout(timeout);
    timeout = setTimeout(() => func.apply(this, args), wait);
  };
}

export const getDimensions = () => {
    const [dimension, setDimension] = useState([window.innerWidth, window.innerHeight]);

    useEffect(() => {
        const handleResize = debounce(() => {
            setDimension([window.innerWidth, window.innerHeight])
        }, 100);
        window.addEventListener("resize", handleResize);
        return () => window.removeEventListener("resize", handleResize)
    }, []);
    
    return dimension;
};

然后修改Navbar.tsx,修正传值问题,添加key强制更新:

// Navbar.tsx
const Navbar: React.FC<NavbarProps> = () => {
  const [windowWidth, windowHeight] = getDimensions();
  // 原有逻辑...
  return (
     <MobileNavWrapper
        initial={false}
        animate={menuIsOpen ? "open" : "closed"}
        custom={windowHeight}
        ref={ref}
        menuIsOpen={menuIsOpen}
      >
        <MobileNavBackground 
          key={windowHeight}
          variants={sidebar} 
          custom={windowHeight} 
        />
        <MobileNav menuIsOpen={menuIsOpen} toggleMenu={toggleMenu} />
        <MenuToggle toggle={() => toggleMenu()} />
      </MobileNavWrapper>
   )
}

你现有的sidebar配置是正确的,无需修改。


内容的提问来源于stack exchange,提问作者Lars van der Niet

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 01:48:02