Next.js App Router+Redux-Toolkit SSR页面导航后未重置初始状态
解决Next.js App Router中Redux状态页面切换不重置的问题
Redux store在Next.js App Router中是全局单例,客户端路由导航(<a>标签跳转)不会触发页面刷新,因此状态会持续保留。要实现页面切换时自动重置状态,可采用以下几种方案:
方案1:全局监听路由变化,重置指定状态
在根layout组件中监听路由路径变化,每次路径切换时触发状态重置:
- 先在Redux slice中添加重置reducer:
// features/counter/counterSlice.js import { createSlice } from '@reduxjs/toolkit'; const initialState = { value: 0, pageData: '' }; export const counterSlice = createSlice({ name: 'counter', initialState, reducers: { increment: (state) => { state.value += 1; }, setPageData: (state, action) => { state.pageData = action.payload; }, // 新增重置状态的reducer resetState: () => initialState } }); export const { increment, setPageData, resetState } = counterSlice.actions; export default counterSlice.reducer;
- 在根layout中监听路由并执行重置:
// app/layout.js 'use client'; import { usePathname, useSearchParams } from 'next/navigation'; import { useEffect } from 'react'; import { useDispatch } from 'react-redux'; import { resetState } from '@/app/features/counter/counterSlice'; export default function RootLayout({ children }) { const pathname = usePathname(); const searchParams = useSearchParams(); const dispatch = useDispatch(); useEffect(() => { // 路由路径或查询参数变化时,重置状态 dispatch(resetState()); }, [pathname, searchParams, dispatch]); return ( <html lang="en"> <body>{children}</body> </html> ); }
方案2:页面卸载时重置专属状态
如果不同页面的状态独立,可在单个页面组件的卸载阶段重置对应状态:
// app/page1/page.js 'use client'; import { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { setPageData, resetState } from '../features/counter/counterSlice'; export default function Page1() { const dispatch = useDispatch(); const pageData = useSelector(state => state.counter.pageData); useEffect(() => { // 页面加载时设置专属数据 dispatch(setPageData('Page 1 专属数据')); // 页面卸载时重置状态 return () => { dispatch(resetState()); }; }, [dispatch]); return ( <div> <h1>Page 1</h1> <p>当前数据:{pageData}</p> <a href="/page2">跳转到Page2</a> </div> ); }
方案3:使用页面专属状态key(多页面独立状态场景)
如果需要保留其他页面状态,仅清除当前页面的状态,可以为每个页面的状态添加路径标识:
- 创建页面专属状态slice:
// features/pageData/pageDataSlice.js import { createSlice } from '@reduxjs/toolkit'; const initialState = {}; export const pageDataSlice = createSlice({ name: 'pageData', initialState, reducers: { setPageData: (state, action) => { const { path, data } = action.payload; state[path] = data; }, clearPageData: (state, action) => { delete state[action.payload]; }, clearAllPageData: () => initialState } }); export const { setPageData, clearPageData, clearAllPageData } = pageDataSlice.actions; export default pageDataSlice.reducer;
- 在页面组件中使用:
// app/page1/page.js 'use client'; import { useEffect } from 'react'; import { usePathname } from 'next/navigation'; import { useDispatch, useSelector } from 'react-redux'; import { setPageData, clearPageData } from '../features/pageData/pageDataSlice'; export default function Page1() { const pathname = usePathname(); const dispatch = useDispatch(); const pageData = useSelector(state => state.pageData[pathname] || ''); useEffect(() => { dispatch(setPageData({ path: pathname, data: 'Page 1 专属数据' })); return () => { dispatch(clearPageData(pathname)); }; }, [dispatch, pathname]); return ( <div> <h1>Page 1</h1> <p>当前数据:{pageData}</p> <a href="/page2">跳转到Page2</a> </div> ); }
内容的提问来源于stack exchange,提问作者Neo Genesis
相关产品推荐
相关产品推荐

