Promise已完成仍显示pending?React异步请求分页报错求助
问题分析与解决方案
核心问题
- 异步数据处理错误:直接将
fetchRecords返回的Promise赋值给data变量,导致data是Promise对象而非实际数组,调用slice方法自然抛出TypeError。 - 未遵循React状态与生命周期规则:组件渲染阶段同步执行异步代码,未用状态存储数据,也未通过
useEffect控制请求时机,导致数据未就绪就被使用。 - 冗余代码:
fetchRecords中return await data完全多余,response.json()已返回解析后的结果,无需额外await。
修改后的代码
import { useState, useEffect } from "react" import ReactPaginate from "react-paginate" import Record from "../components/Record" import FieldName from "../components/FieldName" // 补全fieldNames定义(根据实际业务调整字段名) const fieldNames = ["记录ID", "字段A", "字段B"]; const Index = (props) => { const fetchRecords = async (currentPage) => { const response = await fetch("https://medwallet-backend.onrender.com/data", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ currentPage }) }) // 移除冗余await,直接返回解析后的JSON数据 return response.json() } const [currentPage, setCurrentPage] = useState(1) // 用状态存储接口返回的数组数据 const [recordsData, setRecordsData] = useState([]) // 加载状态,避免数据未就绪时渲染报错 const [isLoading, setIsLoading] = useState(true) // 监听页码变化,触发数据请求 useEffect(() => { const loadRecords = async () => { setIsLoading(true) try { const data = await fetchRecords(currentPage) // 确保存入状态的是数组,兼容后端可能的返回格式 setRecordsData(Array.isArray(data) ? data : []) } catch (error) { console.error("加载数据失败:", error) setRecordsData([]) } finally { setIsLoading(false) } } loadRecords() }, [currentPage]) const recordsPerPage = 10 const lastIndex = currentPage * recordsPerPage const firstIndex = lastIndex - recordsPerPage const records = recordsData.slice(firstIndex, lastIndex) const numPages = Math.ceil(recordsData.length / recordsPerPage) const handlePageClick = (e) => { const page_number = e.selected + 1 setCurrentPage(page_number) } // 加载中占位 if (isLoading) { return <div>加载中...</div> } return <div className="index-container"> <div className="field-names"> {fieldNames.map((fieldName) => <FieldName fieldName={fieldName} key={fieldName} /> )} </div> <div className="records"> {records.length > 0 ? ( records.map((record) => <Record record={record} key={record.record_id}/> ) ) : ( <div>暂无数据</div> )} </div> {/* 只有总页数大于1时渲染分页组件 */} {numPages > 1 && ( <ReactPaginate previousLabel={"Prev"} nextLabel={"Next"} breakLabel={"..."} pageCount={numPages} marginPagesDisplayed={2} pageRangeDisplayed={3} onPageChange={handlePageClick} containerClassName={"pagination justify-content-center"} pageClassName={"page-item"} pageLinkClassName={"page-link"} previousClassName={"page-item"} previousLinkClassName={"page-link"} nextClassName={"page-item"} nextLinkClassName={"page-link"} breakClassName={"page-item"} breakLinkClassName={"page-link"} activeClassName={"active"} /> )} </div> } export default Index
关键改动说明
- 状态管理:新增
recordsData存储接口返回的数组,isLoading控制加载状态,确保数据就绪后再执行数组操作。 - 异步请求时机:通过
useEffect监听currentPage,在组件挂载或页码变化时触发请求,符合React生命周期规则。 - 错误处理:添加
try/catch捕获请求异常,避免组件崩溃。 - 用户体验优化:增加加载中、无数据的提示,分页组件仅在有必要时渲染。
- 代码简化:移除冗余的
await,优化请求逻辑。
内容的提问来源于stack exchange,提问作者ceeb
相关产品推荐
相关产品推荐

