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

将组件设为Async时Next.js抛出错误,求生产可用解决方案

问题分析

你遇到的错误核心原因是:在Next.js客户端组件中,同时使用了React Hooks(useSession)和顶级await(await fetchVoiceCalls(token))。React Hooks必须在组件渲染的同步阶段调用,而异步组件的顶级await会打乱Hooks的执行顺序,触发React的Hooks规则错误。

解决办法

既然你不想用实验性的use钩子,我们可以用标准的useEffect结合状态管理来处理异步数据请求,同时避免不必要的重复请求:

步骤1:标记为客户端组件(App Router 必需)

如果组件在App Router目录下,先添加'use client'指令——因为useSession是客户端Hook,只能在客户端组件中使用。

步骤2:用useEffect+状态管理替代顶级await

通过useState管理数据、加载状态和错误状态,用useEffect在session变化时触发数据请求,确保只有token改变时才重新发起请求,避免无效调用。

修改后的代码:

'use client'; // App Router 下必须添加

import { useSession } from "next-auth/react";
import { useState, useEffect } from "react";

export default function StatsPage() {
  const { data: session } = useSession();
  const [voiceData, setVoiceData] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // 提取token,简化逻辑
  const token = session?.user?.data?.auth_tokens["bearer-token"] || "";

  useEffect(() => {
    // 无token时直接返回,避免无效请求
    if (!token) return;

    const fetchData = async () => {
      setIsLoading(true);
      setError(null);
      try {
        const data = await fetchVoiceCalls(token);
        setVoiceData(data);
      } catch (err) {
        setError("获取通话数据失败");
        console.error(err);
      } finally {
        setIsLoading(false);
      }
    };

    fetchData();
  }, [token]); // 依赖token,仅当token变化时重新请求

  // 渲染不同状态的UI
  if (isLoading) return <div>加载中...</div>;
  if (error) return <div>错误:{error}</div>;
  if (!voiceData && !token) return <div>请先登录</div>;

  return (
    <div>
      <h1>通话统计</h1>
      <p>{voiceData}</p>
    </div>
  );
}

async function fetchVoiceCalls(token: string) {
  const requestOptions = {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${token}`,
    },
  };
  const res = await fetch(`end-point-here`, requestOptions);
  
  // 检查响应状态,主动抛出错误
  if (!res.ok) {
    throw new Error(`请求失败:${res.status}`);
  }
  
  // 可根据实际接口返回解析数据,比如 return res.json();
  return "something";
}

关键改动说明

  • 移除组件的async声明,避免顶级await破坏Hooks执行规则
  • 用useEffect监听token变化,仅在token有效且更新时发起请求,杜绝不必要的重复调用
  • 添加加载、错误状态管理,优化用户体验
  • 在fetchVoiceCalls中增加响应状态校验,捕获请求失败场景,避免未处理的Promise错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 17:40:30