如何通过next-redux-wrapper在Next.js页面间共享状态避免重复初始化?
如何避免在Next.js每个页面重复执行Redux初始化Action?
当前我在Next.js项目中使用next-redux-wrapper管理状态,首页和子页面都需要执行相同的两个初始化Action来设置应用初始状态,但目前每个页面都重复写了相同的getInitialProps逻辑,希望能优化避免重复代码。
现有代码示例
首页(pages/index.tsx)
const Home: NextPage = () => { return (<> <Link href='/2'><a>Go to page 2</a></Link> </>) } Home.getInitialProps = wrapper.getInitialPageProps( ({ dispatch }) => async () => { await dispatch(addInitialSources('book')) await dispatch(addCategoriesMenu('book')) } ); export default Home
子页面(pages/[id]/index.tsx)
const SecondPage: NextPage = () => { return (<> <Link href='/'><a>Go Home</a></Link> </>) } SecondPage.getInitialProps = wrapper.getInitialPageProps( ({ dispatch }) => async () => { await dispatch(addInitialSources('book')) await dispatch(addCategoriesMenu('book')) } ); export default SecondPage
pages/_app.tsx配置
import 'tailwindcss/tailwind.css'; import type { AppProps } from 'next/app' import { wrapper } from "@store/store" function MyApp({ Component, pageProps }: AppProps) { return <Component {...pageProps} /> } export default wrapper.withRedux(MyApp)
优化方案
方案1:封装复用的初始化函数
将重复的初始化逻辑抽成独立函数,在需要的页面中直接调用,减少代码重复。
- 创建复用函数(比如
utils/initAppState.ts):
import { addInitialSources, addCategoriesMenu } from '@store/actions'; export const initAppState = async (dispatch: any) => { await dispatch(addInitialSources('book')); await dispatch(addCategoriesMenu('book')); };
- 在页面中调用该函数:
// 首页 Home.getInitialProps = wrapper.getInitialPageProps( ({ dispatch }) => async () => { await initAppState(dispatch); } ); // 子页面 SecondPage.getInitialProps = wrapper.getInitialPageProps( ({ dispatch }) => async () => { await initAppState(dispatch); } );
方案2:在_app.tsx中全局执行初始化
利用_app.tsx作为所有页面的入口,在这里统一执行初始化逻辑,无需每个页面单独配置。
修改pages/_app.tsx:
import 'tailwindcss/tailwind.css'; import type { AppProps } from 'next/app' import { wrapper } from "@store/store"; import { addInitialSources, addCategoriesMenu } from '@store/actions'; function MyApp({ Component, pageProps }: AppProps) { return <Component {...pageProps} /> } MyApp.getInitialProps = wrapper.getInitialAppProps( ({ dispatch }) => async ({ Component, ctx }) => { // 全局执行初始化Action await dispatch(addInitialSources('book')); await dispatch(addCategoriesMenu('book')); // 保留页面自身的getInitialProps逻辑(如果有的话) const pageProps = Component.getInitialProps ? await Component.getInitialProps(ctx) : {}; return { pageProps }; } ); export default wrapper.withRedux(MyApp);
方案3:检查状态是否已初始化,避免重复执行
在初始化逻辑中先判断状态是否已存在,仅当状态未初始化时才执行Action,这样即使多个页面调用也不会重复触发。
修改复用的初始化函数:
import { addInitialSources, addCategoriesMenu } from '@store/actions'; import { selectSources, selectCategoriesMenu } from '@store/selectors'; // 导入对应的状态选择器 export const initAppState = async (dispatch: any, getState: any) => { const state = getState(); // 根据你的状态结构调整判断条件 const hasInitializedSources = !!selectSources(state); const hasInitializedCategories = !!selectCategoriesMenu(state); if (!hasInitializedSources) { await dispatch(addInitialSources('book')); } if (!hasInitializedCategories) { await dispatch(addCategoriesMenu('book')); } };
然后在页面中调用时传入getState:
Home.getInitialProps = wrapper.getInitialPageProps( ({ dispatch, getState }) => async () => { await initAppState(dispatch, getState); } );
内容的提问来源于stack exchange,提问作者relidon
相关产品推荐
相关产品推荐

