如何在React中使用Axios获取API的所有分页数据
如何一次性获取API分页的所有数据?
我尝试从API获取数据,该API返回多页结果:第一页包含10条数据,剩余数据分布在后续页面中。目前我通过常规Axios请求仅能获取第一页的10条数据,请问如何一次性获取所有分页的数据?
现有代码及API信息
组件代码
import React from "react"; import { useState, useEffect } from "react"; import { getJobs } from "../service/jobs"; const MyTable = () => { const [data, setData] = useState([]); useEffect(() => { getJobs() .then(function (response) { setData(response.data.data.data); console.log(response) }) .catch((e) => { console.log("Jobs error", e); }); }, []); useEffect(() => { console.log(data); }, [data]); return ( <div> {data && data.map((d, key) => ( <div key={key} className="d-flex"> <h1>{d.id}</h1> <h1>{d.job_title}</h1> </div> ))} </div> ); }; export default MyTable;
API响应结构
data: current_page: 1 data: (10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}] first_page_url: "http://api/api/v1/jobs?page=1" from: 1 last_page: 2 last_page_url: "http://api/api/v1/jobs?page=2" links: (4) [{…}, {…}, {…}, {…}] next_page_url: "http://api/api/v1/jobs?page=2" path: "http://api/api/v1/jobs" per_page: 10 prev_page_url: null to: 10 total: 13
getJobs函数
export function getJobs() { return axiosClient.get("/jobs"); }
axiosClient配置
const axiosClient = axios.create({ baseURL: api_url_v1, headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': `Bearer ${accessToken}`, } });
解决方案
从API响应可以看到,返回结果包含last_page(总页数)和next_page_url(下一页链接),我们可以基于这两个字段实现批量请求所有页面并合并数据。
步骤1:修改getJobs函数支持分页参数
先让getJobs可以接收页码参数,方便请求指定页面:
export function getJobs(page = 1) { return axiosClient.get(`/jobs?page=${page}`); }
步骤2:实现批量请求逻辑
提供两种实现方式,可根据需求选择:
方式一:并行请求所有页面(高效)
适合已知总页数的场景,用Promise.all一次性发起所有剩余页面的请求,效率更高:
import React from "react"; import { useState, useEffect } from "react"; import { getJobs } from "../service/jobs"; const MyTable = () => { const [data, setData] = useState([]); useEffect(() => { const fetchAllJobs = async () => { try { // 获取第一页数据,拿到总页数 const firstPageRes = await getJobs(); const { last_page, data: firstPageData } = firstPageRes.data.data; // 只有一页的情况直接返回 if (last_page === 1) { setData(firstPageData); return; } // 生成剩余页面的请求Promise数组 const pagePromises = []; for (let page = 2; page <= last_page; page++) { pagePromises.push(getJobs(page)); } // 并行请求所有剩余页面 const otherPagesRes = await Promise.all(pagePromises); // 合并所有页面的数据 const allData = [ ...firstPageData, ...otherPagesRes.flat(res => res.data.data.data) ]; setData(allData); } catch (e) { console.log("Jobs error", e); } }; fetchAllJobs(); }, []); useEffect(() => { console.log(data); }, [data]); return ( <div> {data.map((d) => ( <div key={d.id} className="d-flex"> {/* 用数据唯一ID作为key更稳定 */} <h1>{d.id}</h1> <h1>{d.job_title}</h1> </div> ))} </div> ); }; export default MyTable;
方式二:递归请求下一页(灵活)
如果API的分页规则可能变化,依赖next_page_url递归请求更贴合API设计:
import React from "react"; import { useState, useEffect } from "react"; import axiosClient from "../path/to/axiosClient"; // 导入axiosClient const MyTable = () => { const [data, setData] = useState([]); useEffect(() => { const fetchAllJobs = async (pagePath = "/jobs") => { try { const res = await axiosClient.get(pagePath); const { data: pageData, next_page_url } = res.data.data; // 合并当前页数据到总数据中 setData(prev => [...prev, ...pageData]); // 如果存在下一页链接,继续请求 if (next_page_url) { // 移除baseURL,只保留路径部分(因为axiosClient已配置baseURL) const nextPath = next_page_url.replace(axiosClient.defaults.baseURL, ""); await fetchAllJobs(nextPath); } } catch (e) { console.log("Jobs error", e); } }; fetchAllJobs(); }, []); // 其余渲染代码和之前一致... return ( <div> {data.map((d) => ( <div key={d.id} className="d-flex"> <h1>{d.id}</h1> <h1>{d.job_title}</h1> </div> ))} </div> ); }; export default MyTable;
注意事项
- 并行请求效率高,但如果总页数过多,可能触发API频率限制,此时可考虑添加延迟或分批请求
- 递归请求更灵活,但要注意分页页数不要过多(避免栈溢出,不过一般分页页数不会达到触发栈溢出的量级)
- 列表渲染时建议使用数据的唯一标识(如
d.id)作为key,而非数组索引,避免不必要的重渲染问题
内容的提问来源于stack exchange,提问作者Basil VJ
相关产品推荐
相关产品推荐

