Axios返回数据无法更新React列表问题求助
问题:React中循环Axios请求无法更新列表的解决方案
我需要通过循环发送Axios GET请求,把返回的数据添加到reqs_needed列表中,但列表始终为空——后端能正常返回数据,前端却无法更新列表显示。相关代码如下:
import "./SuggestedClasses.css"; import Axios from "axios"; import { useState, useEffect } from "react"; import TakenClass from "./types"; import { Table, Thead, Tbody, Tr, Th, Td, TableContainer, } from "@chakra-ui/react"; const SuggestedClasses = () => { const mapping: Record<number, string> = { 0: "CI-H", 1: "CI-M", 2: "HASS-S", 3: "HASS-H", 4: "HASS-A", }; localStorage.setItem("requirements_satisfied", "[2, 2, 1, 1, 1]"); const requirements_satisfied = JSON.parse( localStorage.getItem("requirements_satisfied") as string ); var reqs_filled = JSON.parse( localStorage.getItem("requirements_filled") as string ); var reqs_needed: TakenClass[] = []; if (localStorage.getItem("requirements_filled") == null) { localStorage.setItem("requirements_filled", "[0, 0, 0, 0, 0]"); } for (var i = 0; i < requirements_satisfied.length; i++) { if (reqs_filled[i] < requirements_satisfied[i]) { var j = 0; while (j < requirements_satisfied[i] - reqs_filled[i]) { var hass_attribute = null; var communication_requirement = null; if (mapping[i][0] === "C") { hass_attribute = null; communication_requirement = mapping[i]; } else { hass_attribute = mapping[i]; communication_requirement = null; } useEffect(() => { Axios.get("http://localhost:3000/getClass", { data: { hass_attribute: hass_attribute, communication_requirement: communication_requirement, }, }).then((response) => { if (response.data) { reqs_needed.push(response.data); } }); }, []); j++; } } } console.log("reqs_needed.length", reqs_needed.length); return ( <div className="suggestedClassesContainer"> <h4 className="card-header">Suggested Classes</h4> <TableContainer> <Table variant="striped" colorScheme="teal"> <Thead> <Tr> <Th>Num.</Th> <Th>Rating</Th> </Tr> </Thead> <Tbody> {reqs_needed.map((req: TakenClass) => { if (req != null) { return ( <Tr> <Td>{req.subject_id}</Td> <Td>{req.rating}</Td> </Tr> ); } })} </Tbody> </Table> </TableContainer> </div> ); }; export default SuggestedClasses;
错误原因分析
- 未使用React状态管理数据:
reqs_needed是普通变量,不是useState声明的状态——即使push数据也不会触发组件重渲染,且初始打印时异步请求还未完成,所以长度始终为0。 - 违反Hook规则:在
for/while循环内调用useEffect,React要求Hook必须在组件顶层调用,不能在循环、条件判断中使用,会导致组件渲染逻辑混乱。 - Axios GET请求参数错误:GET请求的参数应该通过
params传递,而不是data(data是POST/PUT等请求的参数字段)。 - localStorage初始化逻辑漏洞:当
requirements_filled不存在时,先设置了localStorage,但后续的reqs_filled还是用了之前的null值解析,会直接报错。
修正后的代码
import "./SuggestedClasses.css"; import Axios from "axios"; import { useState, useEffect } from "react"; import TakenClass from "./types"; import { Table, Thead, Tbody, Tr, Th, Td, TableContainer, } from "@chakra-ui/react"; const SuggestedClasses = () => { const mapping: Record<number, string> = { 0: "CI-H", 1: "CI-M", 2: "HASS-S", 3: "HASS-H", 4: "HASS-A", }; // 初始化localStorage,避免null问题 useEffect(() => { if (!localStorage.getItem("requirements_satisfied")) { localStorage.setItem("requirements_satisfied", "[2, 2, 1, 1, 1]"); } if (!localStorage.getItem("requirements_filled")) { localStorage.setItem("requirements_filled", "[0, 0, 0, 0, 0]"); } }, []); // 获取localStorage数据,添加默认值防止null报错 const requirements_satisfied = JSON.parse( localStorage.getItem("requirements_satisfied") || "[2, 2, 1, 1, 1]" ); const reqs_filled = JSON.parse( localStorage.getItem("requirements_filled") || "[0, 0, 0, 0, 0]" ); // 用useState声明状态变量,存储请求结果 const [reqsNeeded, setReqsNeeded] = useState<TakenClass[]>([]); useEffect(() => { // 收集所有需要发送的请求Promise const requestPromises: Promise<TakenClass>[] = []; for (let i = 0; i < requirements_satisfied.length; i++) { const neededCount = requirements_satisfied[i] - reqs_filled[i]; if (neededCount > 0) { const [hassAttribute, communicationRequirement] = mapping[i][0] === "C" ? [null, mapping[i]] : [mapping[i], null]; // 添加对应次数的请求到Promise数组 for (let j = 0; j < neededCount; j++) { requestPromises.push( Axios.get("http://localhost:3000/getClass", { // GET请求用params传递参数 params: { hass_attribute: hassAttribute, communication_requirement: communicationRequirement, }, }).then(response => response.data) ); } } } // 批量处理所有请求,完成后统一更新状态 Promise.all(requestPromises) .then(results => { setReqsNeeded(results); }) .catch(error => { console.error("请求失败:", error); }); }, [requirements_satisfied, reqs_filled]); // 添加依赖项,数据变化时重新请求 return ( <div className="suggestedClassesContainer"> <h4 className="card-header">Suggested Classes</h4> <TableContainer> <Table variant="striped" colorScheme="teal"> <Thead> <Tr> <Th>Num.</Th> <Th>Rating</Th> </Tr> </Thead> <Tbody> {reqsNeeded.map((req, index) => ( <Tr key={index}> <Td>{req.subject_id}</Td> <Td>{req.rating}</Td> </Tr> ))} </Tbody> </Table> </TableContainer> </div> ); }; export default SuggestedClasses;
关键修改点
- 状态管理:用
useState声明reqsNeeded,通过setReqsNeeded更新状态,触发组件重渲染。 - Hook规范:所有
useEffect都在组件顶层调用,循环收集请求参数后批量处理。 - Axios参数修正:GET请求改用
params传递参数,符合HTTP规范。 - localStorage初始化:单独用
useEffect处理初始化,避免渲染时重复设置,同时解析时添加默认值防止null报错。 - 批量请求处理:用
Promise.all等待所有请求完成后统一更新状态,避免多次触发状态更新。
内容的提问来源于stack exchange,提问作者Nayeemur
相关产品推荐
相关产品推荐

