Next.js中Redux组件出现window is not defined错误的解决方法
解决Next.js中Redux Toolkit screenSizeSlice的window未定义与水合问题
问题根源
Next.js的SSR/SSG阶段在服务器端执行代码,服务器环境没有window对象,直接在slice的初始状态中使用window.innerWidth会触发ReferenceError;如果用typeof window !== 'undefined'给服务器/客户端设置不同初始值,会导致服务器渲染的状态与客户端不匹配,引发水合(hydration)错误。
解决方案
核心思路是让服务器端和客户端使用一致的初始状态,再在客户端挂载后动态获取并更新窗口尺寸:
修改screenSizeSlice的初始状态
把依赖window的初始值换成服务器端能安全处理的默认值(比如0或null):import { createSlice } from "@reduxjs/toolkit"; const initialState = { value: 0 // 服务器端安全的默认值 }; const screenSizeSlice = createSlice({ name: 'screenSize', initialState, reducers: { screenSizeResize: (state, actions) => { state.value = actions.payload }, } }) export const { screenSizeResize } = screenSizeSlice.actions export default screenSizeSlice.reducer创建客户端专属的尺寸监听组件
写一个仅在客户端运行的组件,通过useEffect初始化窗口尺寸并监听resize事件:'use client'; // Next.js 13+ 必须添加,确保组件只在客户端执行 import { useEffect } from 'react'; import { useDispatch } from 'react-redux'; import { screenSizeResize } from './path/to/screenSizeSlice'; export default function ScreenSizeListener() { const dispatch = useDispatch(); useEffect(() => { // 更新窗口尺寸的函数 const updateSize = () => { dispatch(screenSizeResize(window.innerWidth)); }; // 初始化时立即获取一次尺寸 updateSize(); // 监听窗口 resize 事件 window.addEventListener('resize', updateSize); // 组件卸载时移除监听 return () => window.removeEventListener('resize', updateSize); }, [dispatch]); return null; // 该组件无需渲染任何UI }在全局入口引入监听组件
在_app.js(Next.js 12及以下)或layout.js(Next.js 13+)中引入这个组件,确保它随应用启动在客户端运行:// 以 _app.js 为例 import ScreenSizeListener from './ScreenSizeListener'; function MyApp({ Component, pageProps }) { return ( <> <ScreenSizeListener /> <Component {...pageProps} /> </> ); } export default MyApp;
原理说明
- 服务器端渲染时,Redux初始状态为
0,服务器和客户端的初始状态一致,避免水合不匹配。 - 客户端挂载后,
useEffect立即执行,获取实际窗口尺寸并更新Redux状态,同时监听resize事件实现实时更新。
内容的提问来源于stack exchange,提问作者Abd11ellah
相关产品推荐
相关产品推荐

