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

如何在Next.js的SSG/SSR中使用Redux Toolkit的dispatch?

报错根本原因

useDispatch 是React专属Hook,仅能在函数组件体或自定义Hook内部调用,而getStaticProps/getServerSideProps是Next.js提供的、在服务端/构建阶段运行的普通Node.js函数,执行时没有React组件的运行上下文,自然会触发Hook调用规则报错,该问题和Redux本身无关,是Hook的运行限制导致的。

无第三方库的解决方案

核心逻辑非常简单:不要在服务端数据获取函数里调用Hook,直接手动实例化store、调用原生dispatch方法,再把预加载的state传递给客户端store做 hydration 即可。

第一步:编写独立的store生成函数

不要使用单例store,改为每次调用都返回全新store实例的函数,避免服务端多个请求共享状态导致污染:

// store/index.js
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from './features/counterSlice'
import userReducer from './features/userSlice'

// 支持传入预加载state初始化
export const makeStore = (preloadedState) => {
  return configureStore({
    reducer: {
      counter: counterReducer,
      user: userReducer
    },
    preloadedState
  })
}

第二步:调整根组件的Provider适配hydration

修改_app.jsx(Pages Router)或根layout(App Router)的逻辑,让客户端store可以复用服务端生成的预加载state:

// pages/_app.jsx (Pages Router示例)
import { Provider } from 'react-redux'
import { makeStore } from '../store'

// 缓存客户端的store实例,避免重复初始化
let clientStore
const getClientStore = (preloadedState) => {
  // 服务端运行时每次返回新实例
  if (typeof window === 'undefined') {
    return makeStore(preloadedState)
  }
  // 客户端运行时首次初始化用预加载state,后续复用现有实例
  if (!clientStore) {
    clientStore = makeStore(preloadedState)
  }
  return clientStore
}

export default function MyApp({ Component, pageProps }) {
  const store = getClientStore(pageProps.preloadedReduxState)
  return (
    <Provider store={store}>
      <Component {...pageProps} />
    </Provider>
  )
}

第三步:在SSG/SSR函数中直接操作store

不需要调用useDispatch,直接实例化store后调用原生dispatch方法,再把预加载的state放到pageProps传递给客户端即可:

getServerSideProps示例:

// pages/user.jsx
import { makeStore } from '../store'
import { fetchUserList } from '../store/features/userSlice'

export async function getServerSideProps() {
  // 生成当前请求专属的store实例
  const store = makeStore()
  // 直接调用dispatch触发同步/异步action,支持await等待异步执行完成
  await store.dispatch(fetchUserList())
  // 将预加载的state传递给页面props
  return {
    props: {
      preloadedReduxState: store.getState()
    }
  }
}

getStaticProps的用法完全一致,仅运行时机从每次用户请求改为构建阶段预执行。

注意事项
  • 服务端每次执行makeStore都会生成独立实例,不会出现不同用户请求的状态串扰问题
  • 客户端hydration时直接复用服务端预拉取的状态,不需要二次请求已经获取过的数据
  • 若使用Next.js 13+ App Router,只需将上述Provider逻辑封装为客户端组件,放到根layout中即可正常使用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 11:36:05