参考错误:window undefined - 开发人员指南
您是否曾经在控制台中看到过此错误并想知道发生了什么?您并不孤单!臭名昭著的“窗口未定义”错误是使用 React、Next.js 或任何服务器端渲染 (SSR) 应用程序的开发人员最常见的麻烦之一。
这个错误是怎么回事?🤔
首先,让我们了解“window”到底是什么。在基于浏览器的 JavaScript 中,“window”是一个代表浏览器窗口的全局对象。它包含各种有用的东西,例如:
问题是什么?这个对象只存在于浏览器中。当你的代码在服务器上运行时(比如在 SSR 期间),没有浏览器,因此也没有 `window` 对象!

发生此错误的常见情况
当您尝试直接在组件中访问窗口属性时(尤其是在初始渲染期间),您会遇到此错误。这通常在检查屏幕尺寸或浏览器功能时发生:
// This will break during SSR const screenWidth = window.innerWidth;
许多浏览器专用库都假设它们在客户端环境中运行。当这些库尝试在服务器端渲染期间访问窗口时,您的应用程序将崩溃:
// Some libraries assume window exists import someLibrary from 'browser-only-library';
localStorage 是客户端存储中经常访问的窗口属性。在服务器渲染期间尝试使用它将触发错误:
// This will fail on the server
const savedData = localStorage.getItem('user-data');如何修复?💪
1. 使用 useEffect Hook
最直接的解决方案是将特定于浏览器的代码包装在 `useEffect` 钩子中:
import { useEffect } from 'react';
function MyComponent() {
useEffect(() => {
// Safe to use window here
const screenWidth = window.innerWidth;
console.log('Screen width:', screenWidth);
}, []);
return My Component;
}2. 检查窗口是否已定义
创建一个实用函数来安全地检查窗口:
const isClient = typeof window !== 'undefined';
function MyComponent() {
if (isClient) {
// Safe to use window here
}
return My Component;
}3. 动态导入(Next.js 解决方案)
对于 Next.js 应用程序,使用带有 `ssr: false` 的动态导入:
import dynamic from 'next/dynamic';
const BrowserOnlyComponent = dynamic(
() => import('../components/BrowserComponent'),
{ ssr: false }
);专业提示🌟
使用这些久经考验的模式避免“窗口未定义”错误:
function useWindowSize() {
const [size, setSize] = useState({ width: 0, height: 0 });
useEffect(() => {
const updateSize = () => {
setSize({
width: window.innerWidth,
height: window.innerHeight
});
};
window.addEventListener('resize', updateSize);
updateSize();
return () => window.removeEventListener('resize', updateSize);
}, []);
return size;
}function MyComponent() {
const [isMounted, setIsMounted] = useState(false);
useEffect(() => {
setIsMounted(true);
}, []);
if (!isMounted) {
return null; // or a loading state
}
return Browser-only content;
}需要注意的常见问题⚠️
测试你的代码
请记住在服务器和客户端环境中测试您的应用程序。以下是一个简单的测试设置:
describe('MyComponent', () => {
it('handles server-side rendering', () => {
// Test SSR scenario
const { container } = render( );
expect(container).toBeInTheDocument();
});
it('handles client-side rendering', () => {
// Mock window object
const { container } = render( );
expect(container).toBeInTheDocument();
});
});结论
“窗口未定义”错误乍一看可能很吓人,但一旦您了解了它发生的原因,处理起来其实很简单。请记住:
如果您想了解有关窗口对象的更多信息,可以阅读 MDN Web Docs。

祝你编码愉快!🚀