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

Next.js Pages Router中tRPC服务端预取数据失效问题排查

问题:Next.js Pages Router中TRPC服务端预取数据后仍显示加载状态

我在Next.js Pages Router中通过服务端预取数据以避免加载状态,同时保留重取功能,使用getServerSideProps在服务端获取数据,generateSSGHelper函数完全参照文档实现(已确认未在其中用req & res生成上下文,不应在此处出错)。

服务端代码:

export const getServerSideProps = async (ctx: GetServerSidePropsContext<{ id: string }>) => {

  const helpers = generateSSGHelper()

  const id = ctx.params?.id

  if (typeof id !== 'string') throw new Error('no id')

  helpers.partner.getById.prefetch({ id })


  return {
    props: {
      trpcState: helpers.dehydrate(),
      id,
    }
  }
}

组件代码:

const SinglePartnerPage: NextPage<{ id : string }> = ({ id }) => {
 
  const partner = api.partner.getById.useQuery({ id }) // <= 服务端已预取

  if (partner.status !== 'success') { // 此条件本不应成立
    console.log('Loading!!')
    return <>Loading...</>
  }

  return (
    ...
  )
}

实际情况是控制台打印了Loading!!,说明查询并未处于success状态,这给组件其他部分带来了问题。请问我哪里操作有误?这种方式是否可行?


解决方案

这种方式完全可行,你的问题出在以下几个常见疏漏:

1. 未等待预取操作完成

prefetch是异步函数,你没有添加await就直接调用dehydrate(),导致服务端还没完成数据预取就生成了空的脱水状态。修改getServerSideProps:

export const getServerSideProps = async (ctx: GetServerSidePropsContext<{ id: string }>) => {
  const helpers = generateSSGHelper()
  const id = ctx.params?.id

  if (typeof id !== 'string') throw new Error('no id')

  // 必须await预取完成
  await helpers.partner.getById.prefetch({ id })

  return {
    props: {
      trpcState: helpers.dehydrate(),
      id,
    }
  }
}

2. 组件未注入脱水状态

你的组件没有接收trpcState props,也没有通过TRPC的Hydrate组件把脱水状态注入客户端查询缓存。修改组件:

import { Hydrate } from '@trpc/next';

// 补充trpcState的props类型
const SinglePartnerPage: NextPage<{ id: string; trpcState: any }> = ({ id, trpcState }) => {
  const partner = api.partner.getById.useQuery({ id });

  if (partner.status !== 'success') {
    console.log('Loading!!')
    return <>Loading...</>
  }

  return (
    <Hydrate state={trpcState}>
      {/* 你的页面内容 */}
    </Hydrate>
  )
}

3. 上下文一致性检查

即使你没在generateSSGHelper中使用req & res,也要确保服务端生成的TRPC上下文和客户端使用的上下文完全匹配(比如用户认证状态、地域信息等)。如果上下文不匹配,TRPC会认为这是一个新的查询,重新发起请求而非使用预取的数据。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 13:32:45