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

NextJS中如何结合session的access_token使用useSWR请求后端数据?

问题与解决方案

问题背景

用NextJS + Next-auth(credentials provider)实现前端认证,后端基于Django。用户通过Django认证后,用户信息和access_token会存在Next-auth的session中。现在想用useSWR从后端拉取数据,需要在请求头里带上session中的access_token,但直接把useSWR放在认证成功的条件分支里,触发了错误:Error: Rendered more hooks than during the previous render.

核心需求:确保所有后端请求的Authorization头都包含自定义后端返回的access_token。

错误原因

React Hooks规则明确要求:不能在条件判断、循环、嵌套函数中调用Hooks。原代码里把useSWR放在if (status == "authenticated")分支里,导致组件渲染时Hooks的调用数量不稳定,触发了上述错误。

解决方案

方案思路

  1. 把useSWR移到组件顶层,严格遵守Hooks调用规则。
  2. 通过动态控制请求URL(未认证时设为null),让useSWR只在认证成功后发起请求。
  3. 让fetcher动态获取当前session的access_token,保证每次请求都携带最新的token。

修正后的代码

import { useSession } from "next-auth/react";
import useSWR from 'swr';
import axios from 'axios'

export default function Profile() {
    const { data: session, status } = useSession();

    // 顶层调用useSWR,未认证时url设为null,不会发起请求
    const url = status === "authenticated" ? "http://mybackend.com/user/" : null;
    // 动态生成fetcher,每次请求都从当前session拿token
    const fetcher = (url) => {
        const config = {
            headers: { Authorization: `Bearer ${session.access_token}` }
        };
        return axios.get(url, config).then(res => res.data);
    };
    const { data, error } = useSWR(url, fetcher);

    // 处理加载状态
    if (status === "loading") {
        return <span>Loading...</span>;
    }

    // 处理未认证状态
    if (status === "unauthenticated") {
        return <span>请先登录</span>;
    }

    // 认证成功后渲染数据
    if (error) return <span>获取数据失败</span>;
    if (!data) return <span>加载数据中...</span>;

    return <span>{data.email}</span>;
}

额外优化建议

可以封装一个全局的axios实例,自动从session中获取token并添加请求头,避免每个组件重复写请求头逻辑:

// utils/axios.js
import axios from 'axios';
import { useSession } from "next-auth/react";

export function useAuthAxios() {
    const { data: session } = useSession();
    const authAxios = axios.create({
        baseURL: "http://mybackend.com/"
    });

    // 请求拦截器,自动添加Authorization头
    authAxios.interceptors.request.use((config) => {
        if (session?.access_token) {
            config.headers.Authorization = `Bearer ${session.access_token}`;
        }
        return config;
    });

    return authAxios;
}

然后在组件中使用:

import { useSession } from "next-auth/react";
import useSWR from 'swr';
import { useAuthAxios } from '../utils/axios';

export default function Profile() {
    const { status } = useSession();
    const authAxios = useAuthAxios();

    const url = status === "authenticated" ? "/user/" : null;
    const fetcher = (url) => authAxios.get(url).then(res => res.data);
    const { data, error } = useSWR(url, fetcher);

    // 状态处理逻辑同上...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 02:10:20