Next.js 14中Axios实例及API服务无法读取Cookie令牌
核心原因
你的问题本质是Next.js 14的服务器/客户端组件渲染模式差异导致的:
StaffTable默认是服务器组件,在服务端执行时,js-cookie无法访问浏览器Cookie,所以Cookies.get('token')返回undefined- 强行将页面改为客户端组件后,又违反了Next.js规则:客户端组件不能是
async函数
解决方案
方案1:服务器组件中用Next.js原生API获取Token(快速适配)
利用Next.js提供的服务器端cookies() API获取令牌,再传递给API服务:
- 修改
staffAPIServices.ts,支持接收token参数:
import axiosInstance from '../../axios/axiosInstance'; export const getStaff = async (token?: string) => { try { const response = await axiosInstance.get('admin/staff', { headers: token ? { Authorization: `Bearer ${token}` } : {} }); if (response.data.status) { return response?.data?.data?.staff; } } catch (err: unknown) { const errorString = err instanceof Error ? err.message : 'Unknown Error'; return err; } };
- 在
StaffTable组件中获取并传递token:
import clsx from 'clsx'; import { getStaff } from '@/app/utils/services/staff/staffAPIServices'; import { cookies } from 'next/headers'; // 导入服务器端Cookie API export default async function StaffTable({ query, page, }: { query: string; page: number; }) { interface ItemType { id: number; name: string; email: string; email_verified_at: string; created_at: string; updated_at: string; deleted_at: string; } const token = cookies().get('token')?.value; // 服务器端获取token const staff = await getStaff(token); // 原组件JSX内容保持不变 return ( <div className="mt-6 flow-root"> {/* ... 原表格代码 ... */} </div> ); }
方案2:客户端组件用数据获取库处理异步请求(适合交互场景)
如果组件需要用户交互,改成客户端组件,用SWR/React Query处理异步数据:
- 修改
StaffTable为客户端组件,用SWR获取数据:
'use client'; import clsx from 'clsx'; import useSWR from 'swr'; import axiosInstance from '@/app/axios/axiosInstance'; // 定义数据获取函数 const fetchStaff = async () => { const response = await axiosInstance.get('admin/staff'); if (response.data.status) { return response.data.data.staff; } throw new Error('Failed to fetch staff'); }; export default function StaffTable({ query, page, }: { query: string; page: number; }) { interface ItemType { id: number; name: string; email: string; email_verified_at: string; created_at: string; updated_at: string; deleted_at: string; } const { data: staff, error } = useSWR('staff', fetchStaff); if (error) return <div>加载员工数据失败</div>; if (!staff) return <div>加载中...</div>; // 原组件JSX内容保持不变 return ( <div className="mt-6 flow-root"> {/* ... 原表格代码 ... */} </div> ); }
此时axiosInstance.ts无需修改,客户端组件中js-cookie可正常访问浏览器Cookie。
方案3:API路由转发请求(生产环境推荐)
通过Next.js API路由作为中间层,在服务端处理授权逻辑,更安全且符合架构设计:
- 创建
app/api/admin/staff/route.ts:
import { cookies } from 'next/headers'; import axios from 'axios'; import { NextResponse } from 'next/server'; export async function GET() { const token = cookies().get('token')?.value; if (!token) { return NextResponse.json({ status: false, message: '未授权' }, { status: 401 }); } try { const response = await axios.get(`${process.env.NEXT_PUBLIC_CLIENT_URL}/admin/staff`, { headers: { Authorization: `Bearer ${token}` }, withCredentials: true }); return NextResponse.json(response.data); } catch (err) { return NextResponse.json({ status: false, message: '获取员工数据失败' }, { status: 500 }); } }
- 修改
staffAPIServices.ts调用本地API路由:
export const getStaff = async () => { try { const response = await fetch('/api/admin/staff'); const data = await response.json(); if (data.status) { return data.data.staff; } } catch (err: unknown) { const errorString = err instanceof Error ? err.message : '未知错误'; return err; } };
这种方式下客户端无需处理token,所有授权逻辑在服务端完成,避免令牌暴露。
内容的提问来源于stack exchange,提问作者reactcoder
相关产品推荐
相关产品推荐

