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

React Query无法从Django API获取关注列表问题排查

React对接Django API获取关注列表失败排查与修复

API响应

向端点http://127.0.0.1:8000/api/chat/landing/发起GET请求,返回的JSON响应包含current_followings数组,每个元素包含id、username等字段:

{
    "current_followings": [
        {
            "id": 1,
            "username": "Amir",
            "email": "Amir@amir.ir",
            "full_name": "amirali",
            "profile_photo": "/media/profile_photo/1000_F_244376003_1smlBNfWYSInMDUFymPuCcms6d1mOqaF_oU9kIP0.jpg",
            "banner_photo": "/media/banner_photo/header.jpg",
            "phone": null,
            "address": "",
            "bio": "",
            "profile_views": 1
        }
    ],
    ...
}

Django 视图代码 (views.py)

接口视图已配置认证权限,通过Follower模型查询并序列化关注数据返回:

from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework import status
from django.core.exceptions import ObjectDoesNotExist
from .models import Follower, BasicUserProfile

class ChatLandingView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        try:
            current_basic_user_profile = get_current_user_profile(request, User, BasicUserProfile)
            current_followings = Follower.objects.filter(follower=current_basic_user_profile).select_related('following')

            followings_serializer = BasicUserProfileSerializer([f.following for f in current_followings], many=True)

            data = {
                "current_followings": followings_serializer.data,
                ...
            }

            return Response(data, status=status.HTTP_200_OK)

        except ObjectDoesNotExist:
            return Response({"error": "Object not found"}, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

React 组件代码

使用React Query结合axios获取数据,包含加载、错误处理与渲染逻辑:

import React from 'react';
import { useQuery } from '@tanstack/react-query';
import axios from 'axios';

const getToken = () => localStorage.getItem('authToken');

const fetchFollowings = async () => {
    const token = getToken();
    if (!token) {
        throw new Error("未找到认证令牌,请登录后重试。");
    }

    const response = await axios.get('http://127.0.0.1:8000/api/chat/landing/', {
        headers: { 'Authorization': `Bearer ${token}` },
    });

    return response.data.current_followings;
};

const ChatLanding = () => {
    const { data: followings = [], error, isLoading } = useQuery({
        queryKey: ['followings'],
        queryFn: fetchFollowings,
    });

    return (
        <div>
            <h2>我的关注列表</h2>
            {isLoading && <p>加载中...</p>}
            {error && <p>{error.message}</p>}
            {followings.length === 0 && !isLoading && !error && (
                <p>暂无关注对象</p>
            )}
            {followings.length > 0 && (
                <ul>
                    {followings.map(following => (
                        <li key={following.id}>
                            <img src={following.profile_photo} alt={following.full_name} />
                            <p>{following.full_name} ({following.username})</p>
                        </li>
                    ))}
                </ul>
            )}
        </div>
    );
};

export default ChatLanding;

问题现象

  • current_followings数组无法在React组件中正常渲染,偶发认证令牌相关错误;
  • 已确认客户端令牌存储与读取正常;
  • 浏览器控制台显示API响应状态码为200,请求成功。

排查与修复方案

可能的核心原因

  1. Django视图缺失必要导入:原代码未导入status和ObjectDoesNotExist,会触发隐性500错误,被全局异常捕获后返回的错误信息未被前端正确处理;
  2. 图片URL路径不完整:API返回的profile_photo是相对路径,前端直接使用会导致资源加载失败,间接影响组件渲染;
  3. 数据类型无兜底处理:若API返回的current_followings非数组(如null),前端followings.map会直接报错;
  4. React Query缓存策略不合理:偶发认证问题可能是令牌时序或过期问题,缺少重试机制会导致单次失败后无法自动恢复;
  5. 查询逻辑冗余:原视图中[f.following for f in current_followings]的列表推导可通过序列化器优化。

具体调整

Django视图端

  • 补充必要导入:添加from rest_framework import status和from django.core.exceptions import ObjectDoesNotExist;
  • 优化序列化逻辑:用values_list替代列表推导,减少内存占用:
    followings_serializer = BasicUserProfileSerializer(
        current_followings.values_list('following', flat=True), 
        many=True
    )
    
  • 增加错误日志:便于排查具体异常原因:
    import logging
    logger = logging.getLogger(__name__)
    ...
    except Exception as e:
        logger.error(f"获取关注列表失败: {str(e)}")
        return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    

React端

  • 补全图片URL:将相对路径拼接为完整后端地址:
    <img src={`http://127.0.0.1:8000${following.profile_photo}`} alt={following.full_name} />
    
  • 增加数据类型校验:确保返回值为数组类型:
    return Array.isArray(response.data.current_followings) ? response.data.current_followings : [];
    
  • 配置React Query重试与缓存:处理偶发请求失败:
    const { data: followings = [], error, isLoading } = useQuery({
        queryKey: ['followings'],
        queryFn: fetchFollowings,
        retry: 1,
        staleTime: 0
    });
    
  • 细化错误捕获:处理API返回的具体错误信息:
    const fetchFollowings = async () => {
        const token = getToken();
        if (!token) {
            throw new Error("未找到认证令牌,请登录后重试。");
        }
        try {
            const response = await axios.get('http://127.0.0.1:8000/api/chat/landing/', {
                headers: { 'Authorization': `Bearer ${token}` },
            });
            return Array.isArray(response.data.current_followings) ? response.data.current_followings : [];
        } catch (err) {
            throw new Error(err.response?.data?.error || "获取关注列表失败");
        }
    };
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 15:19:54