You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 22:32:21