Axios响应未解析问题:React中数据获取与过滤异常排查
问题描述
我使用Axios获取太阳系天体数据并进行过滤时遇到多个异常:
- 初始状态下,返回的数组包含数据但长度显示为0
- 添加
if(data)判断后,数据先显示为null,一段时间后恢复正常 - 加入
if(response && response.ok)判断后,页面完全无内容,推测是Promise未正确解析导致
以下是我的React代码:
import React, { useState, useEffect } from "react"; import axios from "axios"; import ChildComponent from "./Boxes.jsx"; function Data() { const path = "https://api.le-systeme-solaire.net/rest/bodies/"; const [data, setData] = useState(null); const [isLoading, setIsLoading] = useState(true); const [complexBodies, setComplexBodies] = useState([]); const [simpleBodies, setSimpleBodies] = useState([]); useEffect(() => { const fetchData = async () => { await axios .get(path) .then((response) => { if (response && response.ok) { setData(response.data.bodies); setIsLoading(false); } }) .catch((error) => console.log(error)); }; fetchData(); if (data) dataFilter(); }, [path]); const dataFilter = () => { try { console.log(data); const filterComplex = (body) => body.moons != null; const complexBodies = data.filter(filterComplex); setComplexBodies((props) => [...props, ...complexBodies]); console.log(complexBodies.length); const filterSimple = (body) => body.moons == null; const simpleBodies = data.filter(filterSimple); console.log(simpleBodies.length); setSimpleBodies((props) => [...props, ...simpleBodies]); console.log(simpleBodies); } catch (error) { console.log("Error al filtrar"); } }; if (isLoading) { return <></>; } console.log(complexBodies); return ( <div className="Data"> <ChildComponent simpleBodies={simpleBodies} complexBodies={complexBodies} /> </div> ); } export default Data;
问题分析与修复
1. 异步逻辑执行顺序错误
useEffect中调用fetchData后立刻执行dataFilter(),但fetchData是异步操作,此时data仍为初始的null,dataFilter根本不会执行。且React的setState是异步的,组件重新渲染后才会拿到更新后的data,这是导致数据异常的核心原因。
2. Axios响应判断冗余且错误
Axios仅在请求成功(状态码2xx)时进入then分支,response.ok判断完全多余。若接口返回非2xx状态码会直接进入catch,但你的判断会导致部分合法响应无法设置数据,isLoading一直为true,页面空白。
3. 数据过滤时机错误
过滤逻辑不应在useEffect中直接调用,而应在数据获取完成后立即执行,或监听data的变化触发过滤。
4. setState用法错误
设置complexBodies和simpleBodies时使用[...props, ...complexBodies]会导致数据重复累加,直接设置为过滤后的数组即可。
修复后的代码
import React, { useState, useEffect } from "react"; import axios from "axios"; import ChildComponent from "./Boxes.jsx"; function Data() { const path = "https://api.le-systeme-solaire.net/rest/bodies/"; const [isLoading, setIsLoading] = useState(true); const [complexBodies, setComplexBodies] = useState([]); const [simpleBodies, setSimpleBodies] = useState([]); useEffect(() => { const fetchData = async () => { try { const response = await axios.get(path); const bodies = response.data.bodies; // 直接过滤数据,无需存储原始data到state setComplexBodies(bodies.filter(body => body.moons != null)); setSimpleBodies(bodies.filter(body => body.moons == null)); setIsLoading(false); } catch (error) { console.log("请求错误:", error); setIsLoading(false); // 出错后终止加载状态 } }; fetchData(); }, [path]); if (isLoading) { return <div>加载中...</div>; // 替换空内容,提供加载反馈 } return ( <div className="Data"> <ChildComponent simpleBodies={simpleBodies} complexBodies={complexBodies} /> </div> ); } export default Data;
额外优化说明
- 移除冗余的
datastate,直接在请求后处理过滤,简化状态管理 - 统一使用
async/await + try/catch替代then/catch,代码逻辑更清晰 - 加载状态返回提示文本,避免页面空白
- 异常分支设置
isLoading为false,防止页面一直处于加载状态
内容的提问来源于stack exchange,提问作者Fffantasia
相关产品推荐
相关产品推荐

