reactjs - 如何在反应中使用分页,以便对来自 api 的数据进行相应的分页
问题描述
**As the following code only gives the pagination bar**
`<Pagination
activePage={this.state.activePage}
itemsCountPerPage={2}
totalItemsCount={data.length}
pageRangeDisplayed={data.length/3}
onChange={(e) => this.handleClick(e)}
/>`
但我想绑定来自 API 的数据
解决方案
我为商业项目建造的,它看起来很大。它与 fetch 结合在一起。它使用 Bootstrap 类并且看起来不错(恕我直言)
export default class Pagination extends React.Component {
constructor(props) {
super(props);
this.state = {
controlsCount: 5,
pageSize: 10,
pageNumber: 0,
apiUrl: props.apiUrl,
isHistory: false,
};
this.onFetchCallback = props.onFetchCallback;
}
setDefaultValues = () => {
this.setState({
controlsCount: 5,
pageSize: 10,
pageNumber: 0,
apiUrl: this.props.apiUrl,
isHistory: true
});
let pageNumber = UrlHandler.getParam('pageNumber') || this.state.pageNumber;
let pageSize = UrlHandler.getParam('pageSize') || this.state.pageSize;
this.fetchPage(null, pageNumber, pageSize, true);
};
/**
* props:
* apiUrl getter
* changeState setter
*/
static range(from, to) {
let res = [];
for (let i = from; i <= to; i++) {
res.push(i);
}
return res;
}
componentDidMount = () => {
let pageNumber, pageSize;
pageNumber = UrlHandler.getParam('pageNumber') || this.state.pageNumber;
pageSize = UrlHandler.getParam('pageSize') || this.state.pageSize;
this.fetchPage(null, pageNumber, pageSize);
$(window).on(EVENT_ON_HISTORY_CHANGE, this.setDefaultValues)
};
fetchPage = (e = null, pageNumber, pageSize) => {
!!e && e.preventDefault();
Spinner.show();
fetch(this.state.apiUrl + `page?pageNumber=${pageNumber}&pageSize=${pageSize}`)
.then(res => res.json())
.then((respBody) => {
Spinner.hide();
this.updatePaginator(respBody);
this.onFetchCallback({data: respBody.content});
});
};
updatePaginator = (response) => {
let updateHistory = !this.state.isHistory;
this.setState({
pageNumber: response.number,
totalPages: response.totalPages,
pageSize: response.size,
isHistory: false,
},
() => {
UrlHandler.setParams({
pageNumber: this.state.pageNumber,
pageSize: this.state.pageSize
}, updateHistory);
});
};
createPageBtnFirst = () =>
<PageBtn
pageNumber={0}
content="First"
isDisabled={this.state.pageNumber === 0}
fetchPage={this.fetchPage}
/>
createPageBtnLast = () =>
<PageBtn
pageNumber={this.state.totalPages - 1}
content="Last"
isDisabled={this.state.pageNumber === this.state.totalPages - 1}
fetchPage={this.fetchPage}
/>
createPageBtns() {
let from, to;
if (this.state.pageNumber === null || this.state.pageNumber === undefined) {
return;
}
if (this.state.pageNumber < this.state.controlsCount / 2) {
from = 0;
to = this.state.controlsCount - 1;
} else {
from = Math.floor(this.state.pageNumber - this.state.controlsCount / 2 + 1);
to = Math.floor(this.state.pageNumber + this.state.controlsCount / 2);
}
to = to >= this.state.totalPages ? this.state.totalPages - 1 : to;
return (
Pagination.range(from, to).map(i =>
<PageBtn
pageNumber={i}
content={i + 1}
isActive={i === this.state.pageNumber}
fetchPage={this.fetchPage}
/>
)
)
}
render() {
return (
<div className="card-footer d-flex flex-row d-flex justify-content-between">
<PaginationSizes pageSize={this.state.pageSize} fetchPage={this.fetchPage}/>
<nav aria-label="Page navigation " className="text-right">
<ul className="pagination justify-content-center">
{this.createPageBtnFirst()}
{this.createPageBtns()}
{this.createPageBtnLast()}
</ul>
</nav>
</div>
);
}
}
const PageBtn = ({pageNumber, fetchPage, isDisabled, isActive, content}) => (
<li className={`
${isActive ? "page-item active" : "page-item"}
${isDisabled ? 'disabled' : ''}`}>
<a className="page-link hoverable" onClick={(e) => fetchPage(e, pageNumber, UrlHandler.getParam('pageSize'))}>
{content}
</a>
</li>)
export class PaginationSizes extends React.Component {
state = {
pageSizes: [5, 10, 20]
}
render() {
return (
<div className="dropdown ">
Show: <button className="btn dropdown-toggle bg-white border" type="button" id="dropdownMenuButton"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{this.props.pageSize ? this.props.pageSize : 'All'}
</button>
<div className="dropdown-menu" aria-labelledby="dropdownMenuButton">
<a className="dropdown-item"
onClick={(event) => this.props.fetchPage(event, 0, 1000)}>All</a>
{this.state.pageSizes.map(e =>
<a className="dropdown-item"
onClick={(event) => this.props.fetchPage(event, 0, e)}>{e}</a>
)}
</div>
</div>
)
}
}
和 util lib 中的 URLhandler
const UrlHandler = (function () {
let handler = {
state: {},
setParamsFromBar: function () {
UrlHandler.state = new URLSearchParams(location.search);
$(window).trigger(EVENT_ON_HISTORY_CHANGE);
},
getParam: function (param) {
return this.state.get(param);
},
getAllParams: function () {
return this.state.toString();
},
setParams: function (newParams, updateHistory) {
for ( let [param, value] of Object.entries(newParams)){
this.state.set(param, value);
}
updateHistory && this.updateHistory();
},
updateHistory:function () {
const params = {};
for(let [param, value] of this.state.entries()){
params[param] = value;
}
history.pushState(
params,
'page titile',
'?' + this.getAllParams()
)
}
};
$(window).on('popstate', handler.setParamsFromBar);
handler.state = new URLSearchParams(location.search);
return handler
})();
更新,因为我看到我的答案不符合您的问题,因为您正在询问某个库。但是尽管如此,我还是搜索了这样的库,但还是决定自己写一个简单的组件
推荐阅读
- regex - 我想使用正则表达式匹配 Python 中的两个 Url,但是下面的代码给出了错误。我不知道为什么
- c# - 无法从 WPF WebBrowser 访问生成的 DOM
- neo4j - 如何过滤查询中相对于其他节点的多个日期?
- c++ - 我可以在 C++ 上做什么来做一个数字的倒数?
- php - cURL 输入到 DOMDocument UTF-8
- javascript - 500 行对于 React 组件来说太大了吗?
- codenameone - 在 CSS 和不需要的文件中添加数据文件
- bazel - 如何使用 bazel 查询获取 BUILD 文件中的所有测试规则类型?
- php - 来自数据库 php 的动态时隙预订检查
- django - 是否可以在 django 设置中将参数传递给 celery 任务?