Next.js+Redux Toolkit初始化state时getCookie无法取值求助
问题分析与解决方案
你遇到的核心问题是:Next.js的服务端渲染(SSR)特性导致slice初始化时无法读取到cookie。因为你的themeSlice会在服务端和客户端都执行,而服务端环境中cookies-next的getCookie/hasCookie在没有传入req/res参数的情况下,无法获取到请求中的cookie,所以始终返回undefined,初始状态就被设为light。而toggleTheme是在客户端触发的,setCookie能正常写入,但刷新页面后服务端重新初始化slice,又会回到默认的light。
下面是两种可行的解决方案:
方案一:客户端组件中初始化主题状态
1. 修改themeSlice,新增初始化reducer
先把初始状态设为默认值,新增一个setTheme方法用于手动设置主题:
import { createSlice } from "@reduxjs/toolkit" import { setCookie } from 'cookies-next' const initialState = { name: 'light' // 先设默认值,后续在客户端覆盖 } export const Theme = createSlice({ name: "theme", initialState, reducers: { toggleTheme: (state) => { state.name = state.name === "light" ? "dark" : "light" setCookie('theme', state.name) }, setTheme: (state, action) => { state.name = action.payload setCookie('theme', action.payload) } } }) export const { toggleTheme, setTheme } = Theme.actions export default Theme.reducer
2. 在客户端入口组件中初始化主题
在_app.js或layout.tsx(App Router)的客户端组件里,用useEffect读取cookie并同步到Redux:
import { useEffect } from 'react' import { useDispatch } from 'react-redux' import { getCookie } from 'cookies-next' import { setTheme } from '../slices/themeSlice' // 如果是App Router,需要加上"use client"指令 "use client" function MyApp({ Component, pageProps }) { const dispatch = useDispatch() useEffect(() => { // 仅在客户端环境读取cookie const savedTheme = getCookie('theme') || 'light' dispatch(setTheme(savedTheme)) }, [dispatch]) return <Component {...pageProps} /> } export default MyApp
方案二:利用服务端预加载状态(适配SSR)
如果你需要服务端渲染时就正确渲染主题,可以用next-redux-wrapper在服务端获取cookie并传递给Redux初始状态:
1. 配置Redux Store
import { configureStore } from '@reduxjs/toolkit' import themeReducer from './slices/themeSlice' import { createWrapper } from 'next-redux-wrapper' import { getCookie } from 'cookies-next' const makeStore = (context) => { // 服务端环境下通过context.req获取cookie const initialTheme = context?.req ? getCookie('theme', { req: context.req }) : 'light' return configureStore({ reducer: { theme: themeReducer, }, preloadedState: { theme: { name: initialTheme || 'light' } } }) } export const wrapper = createWrapper(makeStore)
2. 用wrapper包裹入口组件
import { wrapper } from '../store' function MyApp({ Component, pageProps }) { return <Component {...pageProps} /> } export default wrapper.withRedux(MyApp)
这样服务端渲染时就能直接读取请求中的cookie,初始状态会和cookie值保持一致,刷新页面后也不会重置。
内容的提问来源于stack exchange,提问作者VIKESIR
相关产品推荐
相关产品推荐

