如何将next-redux-wrapper的Store Provider迁移到Layout组件?
解决Next.js中Redux Provider迁移到Layout组件的问题
核心思路是让getLayout函数同时接收页面元素和pageProps,而非仅传递页面JSX,这样需要Redux的Layout组件就能拿到原始pageProps来初始化Redux Store。
步骤1:修改_app.tsx,传递pageProps给getLayout
调整MyApp组件,让getLayout同时接收页面元素和pageProps,不再在_app中处理Redux逻辑:
// _app.tsx import { NextPage } from "next"; import type { AppProps } from "next/app"; import { ReactElement, ReactNode } from "react"; import "../../styles/globals.css"; type NextPageWithLayoutAndAuth = NextPage & { getLayout?: (page: ReactElement, pageProps: any) => ReactNode; // 新增pageProps参数 auth?: boolean; }; type AppPropsWithLayout = AppProps & { Component: NextPageWithLayoutAndAuth; }; function MyApp({ Component, pageProps }: AppPropsWithLayout) { const getLayout = Component.getLayout || ((page) => page); // 把page和pageProps都传给getLayout return getLayout(<Component {...pageProps} />, pageProps); } export default MyApp;
步骤2:调整withLayout高阶函数,传递pageProps到Layout组件
修改withLayout,让返回的getLayout函数接收pageProps并传递给对应Layout:
// withLayout.tsx import AuthLayout from "../components/auth/AuthLayout"; import AuthReduxLayout from "../components/auth/AuthReduxLayout"; import DefaultLayout from "../components/auth/DefaultLayout"; type LayoutType = "default" | "auth" | "authRedux"; export default function withLayout(layoutType: LayoutType, title: string) { if (layoutType === "auth") { return function getLayout(page: React.ReactElement, pageProps: any) { return <AuthLayout title={title} pageProps={pageProps}>{page}</AuthLayout>; }; } if (layoutType === "authRedux") { return function getLayout(page: React.ReactElement, pageProps: any) { return <AuthReduxLayout title={title} pageProps={pageProps}>{page}</AuthReduxLayout>; }; } return function getLayout(page: React.ReactElement, pageProps: any) { return <DefaultLayout title={title} pageProps={pageProps}>{page}</DefaultLayout>; }; }
步骤3:修改AuthReduxLayout,处理Redux逻辑并传递处理后的props
在需要Redux的Layout中调用wrapper.useWrappedStore,用Provider包裹内容,并把处理后的props传递给子组件:
// AuthReduxLayout.tsx import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; import { Fragment, ReactElement } from "react"; import { Provider } from "react-redux"; import Footer from "../../../src/components/layout/footer"; import Header from "../../../src/components/layout/header"; import { wrapper } from "../../redux/store/store"; const queryClient = new QueryClient(); type AuthReduxLayoutProps = { title: string; pageProps: any; children: ReactElement; }; const AuthReduxLayout = ({ title, pageProps, children }: AuthReduxLayoutProps) => { // 在这里调用useWrappedStore处理pageProps const { store, props: processedProps } = wrapper.useWrappedStore(pageProps); // 克隆子组件,传递处理后的props const updatedChild = React.cloneElement(children, { ...processedProps.pageProps }); return ( <QueryClientProvider client={queryClient}> <Provider store={store}> <Fragment> <Header /> <main>{updatedChild}</main> <Footer /> </Fragment> </Provider> <ReactQueryDevtools initialIsOpen={false} /> </QueryClientProvider> ); }; export default AuthReduxLayout;
原理说明
- 原本
getLayout仅接收页面JSX,现在把pageProps也传递过去,让需要Redux的Layout能拿到原始数据初始化Store。 - 在
AuthReduxLayout中,调用wrapper.useWrappedStore处理pageProps得到store和处理后的props,然后克隆子组件(页面组件)并传递处理后的props。 - 不需要Redux的Layout(比如
DefaultLayout、AuthLayout)可忽略pageProps,直接渲染子组件,完全不加载Redux相关代码。
内容的提问来源于stack exchange,提问作者Mav33rick
相关产品推荐
相关产品推荐

