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

页面重载后首次调用TRPC useQuery出现Null session问题排查

问题:页面重载时TRPC上下文里的NextAuth Session为null

我正在使用Next.js、TRPC、NextAuth(Prisma组件无问题)开发应用,有一个展示元素集合的页面,通过经过身份验证的TRPC useQuery获取集合数据:

function Collection() {
  const { data: session } = useSession();
  const collectionsQuery = trpc.collectionRouter.collection.useQuery();
  if (session) {
    return (
      <div>
        <Layout>
          <h1>Collections</h1>
          <Link href="/collections/add" className="btn btn-sm btn-success mb-2">Add Collection</Link>
          <div>
            {
              collectionsQuery.data && collectionsQuery.data.length != 0 ?
              JSON.stringify(collectionsQuery.data)
              : 
              <div className="p-2">No collections To Display</div>
            }
          </div>
        </Layout>
      </div>
    );
  } else {
    return (
      <div>Not logged</div>
    )
  }
}

页面重载时该查询总是失败,但通过应用菜单导航到其他页面再返回后,所有查询均可成功执行。在服务端context.ts中,页面重载时getSession返回null,后续所有调用均正常:

export async function createContext(opts: trpcNext.CreateNextContextOptions) {
  const session = await getSession(opts);

  if (session == null) {
    console.log("null session");
  }
  return {
    session,
  };
};

补充信息

  • 编辑1:页面重载查询失效时,客户端已正确设置auth cookie,但服务端无法获取该cookie。
  • 编辑2:尝试过相关解决方案,在createTRPCNext/config中添加请求头转发代码,但无效,甚至该代码未被调用:
headers: () => {
  if (ctx?.req) {
    // on ssr, forward client's headers to the server
    return {
      ...ctx.req.headers,
      'x-ssr': '1',
    };
  }
}

解决思路及方案

1. 检查NextAuth Cookie配置

确认NextAuth的session配置中,cookie参数适配运行环境:

  • 本地开发用http时,secure设为false,否则浏览器不会在非HTTPS环境下发cookie到服务端;
  • 生产HTTPS环境下,secure设为true,同时sameSite设为'lax'或'strict'避免跨域问题;
  • 检查cookie.path是否与应用根路径匹配,默认是/,子路径部署时需调整。

示例配置:

// [...nextauth].ts
export default NextAuth({
  session: {
    strategy: 'jwt',
    cookie: {
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      path: '/',
      maxAge: 24 * 60 * 60, // 1天有效期
    },
  },
  // 其他配置...
});

2. 修复TRPC客户端的请求头转发

确保TRPC客户端在SSR时完整转发请求头,完整配置示例:

// trpc/client.ts
export const trpc = createTRPCNext<AppRouter>({
  config({ ctx }) {
    return {
      headers() {
        // SSR环境下转发客户端请求头(含cookie)到TRPC服务端
        if (ctx?.req) {
          return {
            ...ctx.req.headers,
            'x-trpc-source': 'ssr',
          };
        }
        return {};
      },
    };
  },
  ssr: false, // 禁用SSS缓存避免 stale 数据问题
});

同时确认createContext正确传递请求对象给getSession:

// trpc/context.ts
export async function createContext(opts: trpcNext.CreateNextContextOptions) {
  // 明确传递req和res给getSession
  const session = await getSession({ req: opts.req, res: opts.res });
  return { session };
}

3. 调整页面渲染模式

如果页面用静态生成(SSG),getSession在构建阶段无法获取用户会话,导致SSR时session为null,可通过以下方式修改:

  • 启用服务器端渲染(SSR):在页面组件添加getServerSideProps:
// pages/collections.tsx
export const getServerSideProps = async () => {
  return { props: {} };
};

function Collection() {
  // 组件内容...
}
  • 禁用SSR强制客户端渲染:用Next.js的dynamic组件:
// pages/collections.tsx
import dynamic from 'next/dynamic';

const Collection = dynamic(() => import('./CollectionComponent'), { ssr: false });

export default Collection;

4. 控制TRPC查询触发时机

避免在session未就绪时触发查询,利用useSession的status状态控制查询启用时机:

function Collection() {
  const { data: session, status } = useSession();
  // 仅会话验证通过后才触发查询
  const collectionsQuery = trpc.collectionRouter.collection.useQuery(undefined, {
    enabled: status === 'authenticated',
  });

  if (status === 'loading') {
    return <div>Loading...</div>;
  }

  if (!session) {
    return <div>Not logged</div>;
  }

  return (
    // 页面内容...
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 10:50:25