You need to enable JavaScript to run this app. 如何将窗口resize事件监听值正确赋值给React State?
优惠活动
大模型
产品
解决方案
定价
更多

如何将窗口resize事件监听值正确赋值给React State?

问题根源

这是React Hooks的经典闭包陷阱问题:

  • 你给useEffect设置了空依赖数组,因此该Effect仅会在组件首次挂载时执行1次
  • 首次执行时绑定的autoResize函数属于首次渲染的作用域,内部读取的isDesktopSize永远是初始值true,即使后续state更新,旧的autoResize也无法读取到最新的状态值
  • 原代码没有添加事件监听的卸载逻辑,组件销毁时会造成内存泄漏
修复方案

优化方案(推荐)

因为状态更新逻辑仅依赖窗口宽度,不需要读取旧的isDesktopSize值,我们可以直接移除不必要的依赖,避免函数重复生成,性能最优:

import React, {useState,useEffect, useCallback} from 'react'
import LeftSideNavbar from './LeftSideNavbar'
import TopNavbar from './TopNavbar'

export default function PostLayout({children}) {
    const [isDesktopSize, setIsDesktopSize] = useState(true)

    const autoResize = useCallback(() => {
        const currentIsDesktop = window.innerWidth >= 768
        console.log("Desktop: " + currentIsDesktop);
        console.log(window.innerWidth);
        setIsDesktopSize(currentIsDesktop)
    }, []) // 无外部依赖,函数仅生成一次

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

    return (
        <>
            <TopNavbar isDesktopSize={isDesktopSize}/>
            <main>
                <LeftSideNavbar/>
                {children}
            </main>
        </>  
    )
}

通用适配方案

如果你的业务逻辑确实需要读取旧的isDesktopSize状态,可以将状态加入依赖,配合useCallback保证事件监听可以正常读取最新状态:

import React, {useState,useEffect, useCallback} from 'react'
import LeftSideNavbar from './LeftSideNavbar'
import TopNavbar from './TopNavbar'

export default function PostLayout({children}) {
    const [isDesktopSize, setIsDesktopSize] = useState(true)

    const autoResize = useCallback(() => {
        console.log("Desktop: " + isDesktopSize);
        console.log(window.innerWidth);
        setIsDesktopSize(window.innerWidth >= 768)
    }, [isDesktopSize]) // 依赖state,state更新时自动生成新的函数

    useEffect(() => {
        window.addEventListener('resize', autoResize)
        autoResize();  
        return () => window.removeEventListener('resize', autoResize)
    }, [autoResize]) // 函数更新时自动重新绑定事件

    return (
        <>
            <TopNavbar isDesktopSize={isDesktopSize}/>
            <main>
                <LeftSideNavbar/>
                {children}
            </main>
        </>  
    )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 07:54:05