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

NextJS中组件如何在页面加载时正确获取显示窗口宽度

报错原因

这个错误基本都出在服务端渲染(SSR)场景:SSR阶段代码运行在Node服务端环境,不存在浏览器专属的window对象,你在useState初始化时直接调用window.innerWidth,服务端执行到这行就会直接抛出ReferenceError: window is not defined。
你之前把初始值写死为0的版本能运行但初始值不准,是因为useEffect只会在组件挂载到客户端浏览器后才执行,首屏渲染阶段用的是初始值0,会出现首屏显示宽度错误,甚至触发React hydration不匹配的警告。

修复方案

核心逻辑分两点:

  • 初始化状态时先判断当前运行环境,只有客户端存在window对象时才读取window.innerWidth,服务端阶段用默认值兜底,从根源避免访问不存在的对象报错
  • 在组件首次挂载的useEffect回调里,第一时间同步一次真实窗口宽度,修正兜底默认值带来的首屏数值不准问题,之后再绑定resize事件监听实现宽度动态更新

修正后的完整代码如下:

import React, { useState, useEffect } from "react";

const WindowTracker = () => {
    const [show, setShow] = useState(true);
    // 用函数式初始化做环境判断,逻辑仅在状态初始化时执行一次,性能更好
    const [windowWidth, setWindowWidth] = useState(() => {
        return typeof window !== "undefined" ? window.innerWidth : 0;
    });

    const triggerToggle = () => {
        setShow(!show);
    };

    useEffect(() => {
        // 组件挂载到客户端后立刻更新真实宽度,兜底初始化默认值
        setWindowWidth(window.innerWidth);
        
        function watchWidth() {
            setWindowWidth(window.innerWidth);
        }

        window.addEventListener("resize", watchWidth);

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

    return (
        <div>
            <button onClick={triggerToggle}>Toggle WindowTracker</button>
            {show && <h1>Window width: {windowWidth}px</h1>}
        </div>
    );
};

export default WindowTracker;

如果你用的是Next.js 13+ App Router这类强制区分服务端/客户端组件的框架,只需要在文件最顶部加一行'use client'声明这是客户端组件,配合上面的环境判断逻辑,就不会再出现window未定义或者初始值不准的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 06:36:21