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

Next.js14 headers调用超出请求域致聊天页无响应求助

问题原因

你在标记了"use client"的客户端组件里直接调用了NextAuth的auth()函数——这个函数仅能在服务器组件、API路由、Server Actions中使用,因为它需要访问请求上下文(如headers),而客户端环境没有这个上下文,因此触发headers was called outside a request scope错误,且由于异步逻辑重复执行,导致错误持续递增、页面无响应。

解决方案

提供两种可行修复方案,按需选择:

方案1:用客户端钩子获取会话+API路由取数据

1. 修改chats.tsx组件

替换await auth()为NextAuth客户端钩子useSession,并通过API请求获取聊天数据:

"use client";

import { useSession } from "next-auth/react";
import Chat from "./chat";
import { useState, useEffect } from "react";
import { IChatDocument } from "@/models/chatModel";

const Chats = () => {
  const [selectedChat, setSelectedChat] = useState<IChatDocument | null>(null);
  const [chats, setChats] = useState<IChatDocument[]>([]);
  const [loading, setLoading] = useState(true);
  const { data: session, status } = useSession();

  useEffect(() => {
    const fetchChats = async () => {
      if (!session?.user?._id) {
        setLoading(false);
        return;
      }
      try {
        const res = await fetch(`/api/chats/${session.user._id}`);
        if (!res.ok) throw new Error("获取聊天列表失败");
        const data = await res.json();
        setChats(data);
      } catch (err) {
        console.error(err);
      } finally {
        setLoading(false);
      }
    };

    if (status === "authenticated") fetchChats();
    else if (status === "unauthenticated") setLoading(false);
  }, [session, status]);

  const handleSelectedChat = (chat: IChatDocument) => setSelectedChat(chat);

  if (loading) return <div>加载聊天中...</div>;

  return (
    <nav>
      <ul>
        {chats.map((chat) => (
          <Chat
            key={chat._id}
            chat={chat}
            handleSelectedChat={handleSelectedChat}
            selectedChat={selectedChat}
          />
        ))}
      </ul>
    </nav>
  );
};

export default Chats;

2. 创建API路由处理数据请求

新建app/api/chats/[userId]/route.ts,在服务器环境中调用getUsersForSidebar:

import { getUsersForSidebar } from "@/lib/data";
import { NextResponse } from "next/server";

export async function GET(_: Request, { params }: { params: { userId: string } }) {
  try {
    const chats = await getUsersForSidebar(params.userId);
    return NextResponse.json(chats);
  } catch (err) {
    console.error(err);
    return NextResponse.json({ error: "获取聊天列表失败" }, { status: 500 });
  }
}

方案2:拆分组件,服务器端取数据+客户端处理状态

1. 新建服务器组件ChatsServer.tsx

负责在服务器环境中获取会话和聊天数据:

import { auth } from "@/auth";
import { getUsersForSidebar } from "@/lib/data";
import ChatsClient from "./ChatsClient";

export default async function ChatsServer() {
  const session = await auth();
  const chats = session?.user ? await getUsersForSidebar(session.user._id) : [];
  return <ChatsClient chats={chats} />;
}

2. 新建客户端组件ChatsClient.tsx

仅负责处理客户端状态和渲染:

"use client";

import Chat from "./chat";
import { useState } from "react";
import { IChatDocument } from "@/models/chatModel";

interface Props {
  chats: IChatDocument[];
}

const ChatsClient = ({ chats }: Props) => {
  const [selectedChat, setSelectedChat] = useState<IChatDocument | null>(null);

  const handleSelectedChat = (chat: IChatDocument) => setSelectedChat(chat);

  return (
    <nav>
      <ul>
        {chats.map((chat) => (
          <Chat
            key={chat._id}
            chat={chat}
            handleSelectedChat={handleSelectedChat}
            selectedChat={selectedChat}
          />
        ))}
      </ul>
    </nav>
  );
};

export default ChatsClient;

最后在页面中导入ChatsServer组件即可。

额外注意
  • 确保getUsersForSidebar函数仅包含服务器端可执行的逻辑(如数据库操作),不要混入客户端代码。
  • 检查auth.ts中的session回调,确认_id已正确添加到session对象中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 13:25:03