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

Next.js 13中如何结合服务端与客户端组件并实现带Token的数据请求

解决NextAuth Token传递到API请求的问题

你的核心矛盾在于:服务端组件无法使用useSession客户端Hook,而组件加async/await会自动转为服务端组件,同时原代码里的fetchData还存在未处理异步的问题(没加await)。下面是三种可行的解决思路:

方案一:保持客户端组件,用Hook处理异步请求

既然已经加了"use client",就把组件完全作为客户端组件,用useEffect处理异步数据获取:

"use client";

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

const fetchData = async (token) => {
  const config = {
    headers: { // axios的Authorization需嵌套在headers对象中
      'Authorization': `Token ${token}`
    }
  };
  const response = await axios.get('http://myAPI.com/data', config);
  return response.data;
};

export default function Home() {
  const { data: session } = useSession();
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const loadData = async () => {
      if (!session?.token) return;
      try {
        const result = await fetchData(session.token);
        setData(result);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    };

    loadData();
  }, [session]);

  if (loading) return <main>加载中...</main>;
  if (error) return <main>请求出错:{error.message}</main>;
  if (!data) return <main>无数据</main>;

  return (
    <main>
      <h1>{data.title}</h1>
    </main>
  );
}

关键修正:

  • 给fetchData补全async/await,修正axios的headers配置结构
  • 用useEffect监听session变化,确保token存在后再发起请求
  • 增加加载、错误状态处理,避免页面渲染异常

方案二:转为服务端组件,用服务端方法获取Session

如果页面需要服务端渲染(比如SEO需求),去掉"use client",改用NextAuth的服务端方法getServerSession获取token:

import axios from "axios";
import { getServerSession } from "next-auth/next";
import { authOptions } from "../api/auth/[...nextauth]"; // 导入你的NextAuth配置文件

const fetchData = async (token) => {
  const config = {
    headers: {
      'Authorization': `Token ${token}`
    }
  };
  const response = await axios.get('http://myAPI.com/data', config);
  return response.data;
};

export default async function Home() {
  const session = await getServerSession(authOptions);
  
  if (!session?.token) {
    return <main>请先登录</main>;
  }

  try {
    const data = await fetchData(session.token);
    return (
      <main>
        <h1>{data.title}</h1>
      </main>
    );
  } catch (err) {
    return <main>请求出错:{err.message}</main>;
  }
}

注意事项:

  • 必须导入项目中已有的NextAuth配置文件(通常在pages/api/auth/[...nextauth].js或app/api/auth/[...nextauth]/route.js)
  • 服务端组件可直接用async/await获取数据,无需客户端Hook
  • 提前处理未登录场景,避免空token导致API请求失败

方案三:封装API路由作为中间层

在项目中创建一个内部API路由,在路由里完成session校验和API转发,前端直接调用该路由即可:

1. 创建API路由文件:app/api/proxy-data/route.js

import axios from "axios";
import { getServerSession } from "next-auth/next";
import { authOptions } from "../auth/[...nextauth]";

export async function GET(request) {
  const session = await getServerSession(authOptions);
  
  if (!session?.token) {
    return new Response(JSON.stringify({ error: "未授权" }), { status: 401 });
  }

  try {
    const config = {
      headers: {
        'Authorization': `Token ${session.token}`
      }
    };
    const response = await axios.get('http://myAPI.com/data', config);
    return new Response(JSON.stringify(response.data), { status: 200 });
  } catch (err) {
    return new Response(JSON.stringify({ error: err.message }), { status: 500 });
  }
}

2. 前端组件调用该路由(客户端/服务端组件通用)

"use client"; // 客户端组件需添加此声明,服务端组件可删除
import axios from "axios";
import { useEffect, useState } from "react";

export default function Home() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const loadData = async () => {
      try {
        const response = await axios.get('/api/proxy-data');
        setData(response.data);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    };

    loadData();
  }, []);

  if (loading) return <main>加载中...</main>;
  if (error) return <main>请求出错:{error.response?.data?.error || error.message}</main>;
  if (!data) return <main>无数据</main>;

  return (
    <main>
      <h1>{data.title}</h1>
    </main>
  );
}

优势:

  • 前端无需处理token逻辑,所有认证校验都在服务端完成
  • 可统一管理API请求的错误、缓存策略
  • 避免在前端暴露第三方API地址,提升安全性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 14:18:29