You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

NextJS服务端渲染(SSR)中如何获取Redux Store?

问题分析与解决方案

你遇到的核心问题是_app.tsx中手动创建了Redux Store,完全绕过了next-redux-wrapper的自动注入逻辑,导致getInitialPropsctx对象里找不到store。下面一步步帮你修复:

1. 移除_app.tsx中手动创建的Store和Persistor

你的MyApp组件里自己调用createStore(persistedReducer)persistStore(store),这和next-redux-wrapper的设计完全冲突——它本来就会帮你在服务端和客户端自动创建并注入Store实例。把这段冗余代码删掉:

// 删掉这两行!
const store = createStore(persistedReducer);
const persistor = persistStore(store);

2. 正确获取next-redux-wrapper注入的Store并配置PersistGate

wrapper.withRedux已经把创建好的Store通过props传给了MyApp,我们只需要在客户端初始化持久化(服务端不需要persistStore)。修改MyApp组件如下:

function MyApp({ Component, pageProps, store }) {
  const Layout = Component.layout || (({ children }) => <> {children} </>);
  // 仅在客户端初始化persistor
  const [persistor, setPersistor] = React.useState(null);
  
  React.useEffect(() => {
    if (typeof window !== 'undefined') {
      // 客户端环境才创建持久化实例
      const persistorInstance = persistStore(store);
      setPersistor(persistorInstance);
    }
  }, [store]);

  // 服务端渲染时直接返回内容,不需要等待PersistGate
  if (typeof window === 'undefined' || !persistor) {
    return (
      <React.Fragment>
        <Head>
          <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
          <title>Coala Admin</title>
        </Head>
        <Layout>
          <Component {...pageProps} />
        </Layout>
      </React.Fragment>
    );
  }

  // 客户端渲染时用PersistGate包裹应用
  return (
    <PersistGate persistor={persistor}>
      <React.Fragment>
        <Head>
          <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
          <title>Coala Admin</title>
        </Head>
        <Layout>
          <Component {...pageProps} />
        </Layout>
      </React.Fragment>
    </PersistGate>
  );
}

3. 现在getInitialProps能正常拿到Store了

wrapper.withRedux已经把Store注入到ctx对象里,你可以直接访问:

MyApp.getInitialProps = async ({ Component, ctx }: AppContext): Promise<AppInitialProps> => {
  console.log(ctx.store); // 现在能正常打印Store实例了!
  let pageProps = {};
  if (Component.getInitialProps) {
    pageProps = await Component.getInitialProps(ctx);
  }
  return { pageProps };
};

额外验证:store/index.ts的配置没问题

你的makeStore函数逻辑是对的——服务端返回普通Store,客户端返回包含persistor的扩展Store对象,next-redux-wrapper能正确识别并处理这种结构。

为什么之前找不到Store?

next-redux-wrapperwithRedux高阶组件会在应用启动时自动创建Store,并把它注入到AppContextctx中。但你手动创建了新的Store,相当于覆盖了wrapper的注入逻辑,导致ctx里的Store丢失。


内容的提问来源于stack exchange,提问作者a_lady_on_fire

火山引擎 最新活动