React 中的分页 API 请求
介绍
网络上充斥着 API 请求,大多数情况下,获取的数据只有在需要时才会加载(分页),以确保流畅的用户体验。这是通过从外部源(如 API)获取数据来实现的。本指南重点介绍如何使用 Hacker News API 在 React 中实现分页。喝杯咖啡 ☕,开始编程吧。
设置 React
打开终端并运行以下命令来设置您的 React 项目。您也可以通过访问https://react.new通过 CodeSandbox 获取完全配置的 React 环境。
npx create-react-app my-app
cd my-app
npm start
在浏览器中打开 localhost:3000。你应该会看到一个动画的 React 徽标。
API 端点和数据结构
用于获取数据的 API 端点是https://hn.algolia.com/api/v1/search。此端点接受搜索查询和页码等参数。使用startups查询参数向此端点发出请求,URL 应如下所示:https://hn.algolia.com/api/v1/search ?query=startups 。成功的请求应返回以下结果:
{
hits: [
{
created_at: '2015-04-07T12:07:10.000Z',
title:
"What I'd tell myself about startups if I could go back 5 years",
url:
'http://www.talkingquickly.co.uk/2015/04/what-id-tell-myself-about-startups/',
author: 'vinnyglennon',
points: 865,
story_text: null,
comment_text: null,
num_comments: 273,
story_id: null,
story_title: null,
story_url: null,
parent_id: null,
created_at_i: 1428408430,
relevancy_score: 5955,
_tags: ['story', 'author_vinnyglennon', 'story_9333330'],
objectID: '9333330',
_highlightResult: {
title: {
value:
"What I'd tell myself about <em>startups</em> if I could go back 5 years",
matchLevel: 'full',
fullyHighlighted: false,
matchedWords: ['startups'],
},
url: {
value:
'http://www.talkingquickly.co.uk/2015/04/what-id-tell-myself-about-<em>startups</em>/',
matchLevel: 'full',
fullyHighlighted: false,
matchedWords: ['startups'],
},
author: {
value: 'vinnyglennon',
matchLevel: 'none',
matchedWords: [],
},
},
},
........
],
nbHits: 136242,
page: 0,
nbPages: 50,
hitsPerPage: 20,
exhaustiveNbHits: false,
query: 'startups',
params:
'advancedSyntax=true&analytics=true&analyticsTags=backend&query=startups',
processingTimeMS: 7,
}
此响应中最重要的部分是nbPages(页数)、hitsPerPage(每页结果数)和hits数组,其中包含数据本身。花点时间自己检查一下数据。
提出请求
现在您已经清楚地了解了响应数据,请使用 fetch API 将 hits 数组存储在状态中,如下面的代码片段所示。
import React, { useState } from 'react';
const NewsCard = (props) => {
return (
<div style={{ padding: '20' }}>
<a href={props.url}>
{props.title} by {props.author}
</a>
</div>
);
};
function App() {
const [hits, setHits] = useState([]);
const [isLoaded, setisLoaded] = useState(false);
const [query, setQuery] = useState('startups');
const URL = `https://hn.algolia.com/api/v1/search?query=${query}`;
const handleFetch = () => {
fetch(URL)
.then(response => response.json())
.then(body => {
setData([...body.hits]);
})
.catch(error => console.error('Error', error));
};
return (
<div>
<label>Search</label>
<input type="text" onChange={(event) => setQuery(event.target.value)} />
<button onClick={handleFetch}>Get Data</button>
{isLoaded ? (
hits.map((item) => {
return (
<NewsCard
url={item.url}
title={item.title}
author={item.author}
key={item.objectID}
/>
);
})
) : (
<div></div>
)}
</div>
);
}
export defailt App;
上述代码从输入元素获取查询值并将其存储在状态中。单击按钮时,将向端点发出请求,然后端点将呈现包含 hits 数组中的故事标题的 URL 列表。
实现分页
在您从 API 端点收到的响应中,请注意有一个值显示可用的页面数。这有助于了解页面选项卡的数量或要发出的最大请求数。从头开始处理分页可能非常耗时且令人沮丧,但幸运的是,有一个很棒的库可以轻松实现这一点:React-Paginate。
运行以下命令将 React-Paginate 添加到您的依赖项。
npm install react-paginate --save
import React, { useState } from 'react';
import ReactPaginate from 'react-paginate'; #New
const NewsCard = (props) => {
return (
<div style={{ padding: '20' }}>
<a href={props.url}>
{props.title} by {props.author}
</a>
</div>
);
};
function App() {
const [hits, setHits] = useState([]);
const [pageCount, setPageCount] = useState(1); #New
const [isLoaded, setisLoaded] = useState(false);
const [currentPage, setcurrentPage] = useState(0); #New
const [query, setQuery] = useState('startups');
const URL = `https://hn.algolia.com/api/v1/search?query=${query}&page=${currentPage}`;
const handleFetch = () => {
fetch(URL)
.then(response => response.json())
.then(body => {
setData([...body.hits]);
setPageCount(body.nbPages); #New
setisLoaded(true); #New
})
.catch(error => console.error('Error', error));
};
#New
const handlePageChange = (selectedObject) => {
setcurrentPage(selectedObject.selected);
handleFetch();
};
return (
<div>
<label>Search</label>
<input type="text" onChange={(event) => setQuery(event.target.value)} />
<button onClick={handleFetch}>Get Data</button>
{isLoaded ? (
hits.map((item) => {
return (
<NewsCard
url={item.url}
title={item.title}
author={item.author}
key={item.objectID}
/>
);
})
) : (
<div></div>
)}
#New
{isLoaded ? (
<ReactPaginate
pageCount={pageCount}
pageRange={2}
marginPagesDisplayed={2}
onPageChange={handlePageChange}
containerClassName={'container'}
previousLinkClassName={'page'}
breakClassName={'page'}
nextLinkClassName={'page'}
pageClassName={'page'}
disabledClassNae={'disabled'}
activeClassName={'active'}
/>
) : (
<div>Nothing to display</div>
)}
</div>
);
}
export defailt App;
添加这些 CSS 类可以使分页选项卡看起来更加美观。
.container{
display: flex;
list-style: none;
}
.page{
padding: 10px;
border: 1px solid #dcdcdc;
border-radius: 6px;
margin-right: 10px;
cursor: pointer;
}
.disabled{
cursor: not-allowed;
}
.active{
border: 2px solid #000;
font-weight: bold;
}
.previous{
padding: 10px;
border-radius: 6px;
margin-right: 10px;
cursor: pointer;
}
.break{
padding: 10px;
}
.next{
padding: 10px;
border-radius: 6px;
margin-right: 10px;
cursor: pointer;
}
理解实施
当前页面被置于状态中,每次用户单击新页面按钮时都会更新。React-Paginate 将回调函数作为名为onPageChange的 prop ,该函数将包含所选页面的对象作为名为selected 的属性。在负责该回调函数 ( handlePageChange ) 中,当前页面的状态会更新,并触发网络请求。
道具:
- pageCount(必需)属性指的是所需的页面总数。
- pageRangeDisplayed(必需)prop 表示显示的页面范围。
- marginPagesDisplayed(必需)表示要显示的页边距的页数。
结论
就是这样!这是在 React 中实现分页的最简单方法。我建议你阅读文档以了解更多信息:React Paginate。你也可以在 Twitter 上关注我@DesmondNyamador。
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~