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,请求成功。
排查与修复方案
可能的核心原因
- Django视图缺失必要导入:原代码未导入
status和ObjectDoesNotExist,会触发隐性500错误,被全局异常捕获后返回的错误信息未被前端正确处理; - 图片URL路径不完整:API返回的
profile_photo是相对路径,前端直接使用会导致资源加载失败,间接影响组件渲染; - 数据类型无兜底处理:若API返回的
current_followings非数组(如null),前端followings.map会直接报错; - React Query缓存策略不合理:偶发认证问题可能是令牌时序或过期问题,缺少重试机制会导致单次失败后无法自动恢复;
- 查询逻辑冗余:原视图中
[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
相关产品推荐
相关产品推荐

