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

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)错误。

解决方案

核心思路是让服务器端和客户端使用一致的初始状态,再在客户端挂载后动态获取并更新窗口尺寸:

  1. 修改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   
    
  2. 创建客户端专属的尺寸监听组件
    写一个仅在客户端运行的组件,通过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
    }
    
  3. 在全局入口引入监听组件
    在_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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 12:12:44