如何让Redux DevTools在Redux Toolkit+Next.js(TypeScript)环境正常工作?
问题分析与解决方案
问题根源
核心问题是每次_app.tsx渲染时都会重新创建Redux Store实例。Redux DevTools默认只会和第一个创建的Store建立连接,后续新生成的Store发出的动作自然不会被追踪——哪怕应用功能本身正常。
在Next.js中,_app.tsx作为全局入口组件,客户端每次路由切换或组件更新都可能触发重新渲染,导致getStore被反复调用,生成多个独立的Store实例。
修复步骤
1. 修改Store文件,实现客户端单例模式
让客户端环境下只创建一次Store,服务端则保持每次请求生成新Store(符合Next.js服务端渲染的无状态要求)。
修改后的store.ts代码:
import { configureStore, ThunkAction, Action, combineReducers } from "@reduxjs/toolkit"; import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux"; import UISlice from '@todoSlice/todoSlice' const rootReducer = combineReducers({ todo: UISlice, }); // 客户端环境下缓存Store实例,避免重复创建 let clientStore: ReturnType<typeof configureStore> | undefined; export default function getStore(incomingPreloadState?: AppState) { // 服务端环境每次都创建新Store;客户端仅在首次调用或无缓存实例时创建 if (typeof window === 'undefined' || !clientStore) { clientStore = configureStore({ reducer: rootReducer, preloadedState: incomingPreloadState, // Redux Toolkit默认在开发环境开启DevTools,生产环境自动关闭,无需额外配置 }); } else if (incomingPreloadState) { // 可选:路由切换需更新初始状态时,可在对应Slice中添加重置动作 // 示例:dispatch(resetTodoState(incomingPreloadState.todo)) } return clientStore; } export type AppState = ReturnType<typeof rootReducer>; export type AppDispatch = ReturnType<typeof getStore>["dispatch"]; export type AppThunk<ReturnType = void> = ThunkAction< ReturnType, AppState, unknown, Action<string> >; export const useAppDispatch = () => useDispatch<AppDispatch>(); export const useAppSelector: TypedUseSelectorHook<AppState> = useSelector;
2. 移除错误的DevTools配置
你之前手动引入redux-devtools-extension的composeWithDevTools并关闭configureStore的内置DevTools,这会导致配置冲突。Redux Toolkit已经内置了DevTools集成,默认在开发环境启用,完全无需额外配置外部包。
3. 保持_app.tsx原有逻辑不变
_app.tsx的代码无需修改,因为我们已经在getStore函数中处理了单例逻辑。
验证效果
- 客户端点击
Add!按钮触发的addTodos动作会被DevTools正常记录,状态更新可见 - 服务端
getServerSideProps中执行的intidialTodos动作不会出现在DevTools中,符合预期
额外说明
如果需要在路由切换时更新客户端Store的初始状态,建议在对应的Slice中添加一个重置动作(比如reset),通过dispatch来更新状态,而不是重新创建Store实例,避免DevTools连接中断。
内容的提问来源于stack exchange,提问作者relidon
相关产品推荐
相关产品推荐

