Next.js中如何在getServerSideProps内执行graphql-codegen生成的mutation
报错核心原因
useGetTokenMutation是Apollo配合React生成的Hook函数,只能在React函数组件、自定义Hook的顶层作用域内调用。而getServerSideProps是Next.js在服务端独立运行的普通异步函数,完全不在React组件的渲染上下文里,在这里直接调用Hook必然触发React的Hook规则校验报错。
你提到的graphql-codegen-apollo-next-ssr插件不生成Mutation的服务端适配代码不是配置错误,这个插件本身的设计定位就是给SSR阶段的读操作(Query)生成预取代码,Mutation作为带写副作用的操作,从设计之初就没被纳入插件的SSR适配范围。
正确实现方式
不需要等插件支持Mutation的SSR适配,直接在getServerSideProps中通过Apollo Client实例手动调用mutation即可,逻辑非常直接:
- 准备好可在服务端运行的Apollo Client实例,注意不要用依赖浏览器API(比如
window、document)的客户端实例,同时要保证不同用户请求之间的实例状态隔离,避免数据串扰。 - 在
getServerSideProps中拿到实例后,直接调用实例自带的mutate方法,传入codegen生成的Mutation文档节点和对应变量即可,完全不需要使用Hook。
参考实现代码:
// 导入codegen生成的Mutation文档,和你组件里useGetTokenMutation依赖的是同一份gql定义 import { GetTokenDocument } from '@/generated/graphql'; // 导入你项目中封装好的服务端Apollo Client初始化方法 import { initServerApolloClient } from '@/lib/apollo/server'; export async function getServerSideProps(context) { // 基于当前请求上下文初始化服务端Apollo Client const client = initServerApolloClient({ req: context.req, res: context.res }); // 直接执行mutation,传参逻辑和组件里调用getTokenMutation完全一致 const mutationResult = await client.mutate({ mutation: GetTokenDocument, variables: { // 填入你需要传的参数,比如从context里拿到的code、认证信息等 } }); const token = mutationResult.data?.getToken; // 后续业务逻辑,比如把token注入页面props、做重定向、权限校验等 return { props: { token } }; }
注意事项
- 不要把有明确用户交互触发的写操作(比如提交表单、下单、修改用户资料)放到
getServerSideProps里执行。getServerSideProps会在每次页面请求时自动运行,放这类操作很容易出现非预期的重复触发。如果是获取服务端token、校验接口权限这类无用户感知的副作用操作,放在这里执行是没问题的。 - 如果你用的是其他GraphQL客户端(比如urql、graphql-request),核心逻辑完全一致:不要调用React Hook封装的方法,直接导入服务端可用的客户端实例,调用实例的mutation执行方法,传入对应请求文档和参数即可。
- 服务端使用的Apollo Client不要做成全局单例存储用户态数据(比如认证token、用户个性化缓存),否则会出现不同用户请求之间的数据泄露问题。
内容的提问来源于stack exchange,提问作者sev
相关产品推荐
相关产品推荐

