通过 table 的 reactjs 分页
reactjs paging through the table
我正在使用 api 列出数据。
我用 reactstrap table 向用户显示我收到的数据。
但是我想分页。
一页最多显示6条记录,其他记录在后续页面显示。
import React, { Component, useState } from "react";
import withAuth from "../../components/helpers/withAuth";
import {
Button,
Card,
CardBody,
CardHeader,
Col,
Pagination,
PaginationItem,
PaginationLink,
Row,
Table,
} from "reactstrap";
class CustomerDebt extends Component {
constructor(props) {
super(props);
this.domain = `http://127.0.0.1:8000`;
this.state = {
isLoaded: true,
items: [], //Customer Debt Items
};
}
async componentDidMount() {
//customer debt list
await fetch(
`${this.domain}/api/debt/list?customer=` +
this.props.customerInfo.customer.id,
{
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
"Content-Type": "application/json"
}
}
)
.then(res => {
if (res.ok) {
return res.json();
} else {
return res.json().then(err => Promise.reject(err));
}
})
.then(json => {
this.setState({
items: json,
});
this.abortController.abort();
})
.catch(error => {
return error;
});
}
render() {
const { isLoaded, items } = this.state;
if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className={"animated fadeIn container-fluid"}>
<Row>
<Col>
<Card>
<CardHeader>
<i className="fa fa-align-justify" /> Müşteri Borcu
</CardHeader>
<CardBody>
<Table hover bordered striped responsive size="sm">
<thead>
<tr>
<th width={"10"} />
<th width={"15"}>No</th>
<th style={{ display: "none" }}>User</th>
<th style={{ display: "none" }}>Key</th>
<th style={{ display: "none" }}>CreatedUserKey</th>
<th width={"40"}>Total debt</th>
<th width={"40"}>Received amount</th>
<th scope={"row"}>Description</th>
<th width={"20"}>Payment Date</th>
</tr>
</thead>
<tbody>
{items.map(item => {
return (
<tr key={item.id}>
<td>{item.id}</td>
<td style={{ display: "none" }}>{item.user}</td>
<td style={{ display: "none" }}>{item.debtKey}</td>
<td style={{ display: "none" }}> {" "} {item.createduserKey}{" "} </td>
<td>{item.totalDebt}</td>
<td>{item.receivedAmount}</td>
<td>{item.description}</td>
<td> {new Date(item.paymentDate).toLocaleString()} </td>
</tr>
);
})}
</tbody>
</Table>
<nav>
<Pagination>
<PaginationItem>
<PaginationLink previous tag="button">
Back
</PaginationLink>
</PaginationItem>
<PaginationItem active>
<PaginationLink tag="button">1</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink tag="button">2</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink tag="button">3</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink tag="button">4</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink next tag="button">
Next
</PaginationLink>
</PaginationItem>
<PaginationItem></PaginationItem>
</Pagination>
</nav>
</CardBody>
</Card>
</Col>
</Row>
</div>
);
}
}
}
export default CustomerDebt;
您需要根据记录数动态生成分页按钮,然后在按下分页按钮时,设置页码,如果要根据页码和每页大小显示项目,则创建一个数组。
这是示例代码,可让您了解如何完成此操作。这不是完整的或错误证明,因为这是你的工作。我希望能明白。
class CustomerDebt extends Component {
constructor(props) {
super(props);
this.domain = `http://127.0.0.1:8000`;
this.state = {
isLoaded: true,
items: [], //Customer Debt Items,
pageItems: [],
page: 0,
pageSize: 6
};
}
async componentDidMount() {
const { pageSize } = this.state;
//customer debt list
await fetch(
`${this.domain}/api/debt/list?customer=` +
this.props.customerInfo.customer.id,
{
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
"Content-Type": "application/json"
}
}
)
.then(res => {
if (res.ok) {
return res.json();
} else {
return res.json().then(err => Promise.reject(err));
}
})
.then(json => {
this.setState({
items: json,
pageItems: json.slice(0, pageSize)
});
this.abortController.abort();
})
.catch(error => {
return error;
});
}
render() {
const { isLoaded, pageItems, items, page, pageSize } = this.state;
const pages = Math.ceil(items.length / page);
const paginationItems = Array(pages).fill('').map((i, index) => (
<PaginationItem active={page === index}>
<PaginationLink tag="button" onClick={() => this.setState({page: index })}}>2</PaginationLink>
</PaginationItem>
));
if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className={"animated fadeIn container-fluid"}>
<Row>
<Col>
<Card>
<CardHeader>
<i className="fa fa-align-justify" /> Müşteri Borcu
</CardHeader>
<CardBody>
<Table hover bordered striped responsive size="sm">
<thead>
<tr>
<th width={"10"} />
<th width={"15"}>No</th>
<th style={{ display: "none" }}>User</th>
<th style={{ display: "none" }}>Key</th>
<th style={{ display: "none" }}>CreatedUserKey</th>
<th width={"40"}>Total debt</th>
<th width={"40"}>Received amount</th>
<th scope={"row"}>Description</th>
<th width={"20"}>Payment Date</th>
</tr>
</thead>
<tbody>
{pageItems.map(item => {
return (
<tr key={item.id}>
<td>{item.id}</td>
<td style={{ display: "none" }}>{item.user}</td>
<td style={{ display: "none" }}>{item.debtKey}</td>
<td style={{ display: "none" }}> {" "} {item.createduserKey}{" "} </td>
<td>{item.totalDebt}</td>
<td>{item.receivedAmount}</td>
<td>{item.description}</td>
<td> {new Date(item.paymentDate).toLocaleString()} </td>
</tr>
);
})}
</tbody>
</Table>
<nav>
<Pagination>
<PaginationItem onClick={() => this.setState(prev => ({page: prev.page -1}))}>
<PaginationLink>
Back
</PaginationLink>
<PaginationItem onClick={() => this.setState(prev => ({page: prev.page + 1}))}>
<PaginationLink next tag="button">
Next
</PaginationLink>
</PaginationItem>
<PaginationItem></PaginationItem>
</Pagination>
</nav>
</CardBody>
</Card>
</Col>
</Row>
</div>
);
}
}
}
export default CustomerDebt;
首先,您需要创建两个变量来帮助您跟踪当前页面和 table 的大小。我们称它们为 pageSize
和 pageIndex
class App extends React.Component {
state = {
pageSize: 2, // <- 2 items will be shown on single page
pageIndex: 0, // 0 is a default page to show
items: []
};
...
然后您需要从外部源获取一些数据。在我的示例中,我只是创建了一个模拟数组并将其设置为状态。
...
componentDidMount() {
const data = [
{ id: 1, name: "Roman" },
{ id: 2, name: "Oleh" },
{ id: 3, name: "Vitalii" },
{ id: 4, name: "Mikhail" },
{ id: 5, name: "Vladislav" },
{ id: 6, name: "Anton" },
{ id: 7, name: "Yurii" },
{ id: 8, name: "Volodymir" },
{ id: 9, name: "Taras" }
];
this.setState({ items: data });
}
...
之后,您需要创建辅助函数并在其中放置 table 导航逻辑。我们将它们命名为 handlePrevPageClick
和 handleNextPageClick
.
handlePrevPageClick
应该减少点击时的当前索引。此外,我们需要防止用户滚动太多。所以,如果 pageIndex
不为 0 - 减少,否则停止减少。
handleNextPageClick
的逻辑应该和handlePrevPageClick
完全一样。唯一的东西是颠倒的。不要让用户过度滚动您的 table。为此,我们需要了解我们有多少页。通过除以 this.state.items / this.state.pageSize
我们将得到可用页面的总数。假设我们的 table 有 12 个项目,页面大小为 5。因此,12 / 5 = 2.4。这意味着我们将有 2 个页面已满载,还剩下 4 个项目。通过使用 Math.ceil(12 / 5)
我们将得到 3 - 是 table 的可用页面总数的整数。之后,我们只添加简单的条件,如果 pageIndex
< 3,如果是 - 增加 pageIndex
,否则停止。
...
handlePrevPageClick(event) {
this.setState(prevState => ({
pageIndex: prevState.pageIndex > 0 ? prevState.pageIndex - 1 : 0
}));
}
handleNextPageClick(event) {
this.setState(prevState => ({
pageIndex:
prevState.pageIndex <
Math.ceil(prevState.items.length / prevState.pageSize)
? prevState.pageIndex + 1
: prevState.pageIndex
}));
}
最后想到的是用正确的行呈现 table。为此,您可以使用 .slice(...)
。第一个参数是页面的左边界,第二个参数是页面的右边界。
首页
this.state.pageIndex * this.state.pageSize, // 0 * 5 = 0
this.state.pageIndex * this.state.pageSize + this.state.pageSize // 0 * 5 + 5 = 5
显示从索引 0 到 5 的元素。
第二页
this.state.pageIndex * this.state.pageSize, // 1 * 5 = 5
this.state.pageIndex * this.state.pageSize + this.state.pageSize // 1 * 5 + 5 = 10
显示从索引 5 到 10 的元素。
...
render() {
return (
<>
<button onClick={event => this.handlePrevPageClick(event)}>
Prev page
</button>
<button onClick={event => this.handleNextPageClick(event)}>
Next page
</button>
<table border="1">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
</tr>
</thead>
<tbody>
{this.state.items
.slice(
this.state.pageIndex * this.state.pageSize,
this.state.pageIndex * this.state.pageSize + this.state.pageSize
)
.map(item => (
<tr>
<td>{item.id}</td>
<td>{item.name}</td>
</tr>
))}
</tbody>
</table>
</>
);
}
}
如果您想查看完整的工作示例,请使用此 CodeSandbox link
我正在使用 api 列出数据。 我用 reactstrap table 向用户显示我收到的数据。 但是我想分页。
一页最多显示6条记录,其他记录在后续页面显示。
import React, { Component, useState } from "react";
import withAuth from "../../components/helpers/withAuth";
import {
Button,
Card,
CardBody,
CardHeader,
Col,
Pagination,
PaginationItem,
PaginationLink,
Row,
Table,
} from "reactstrap";
class CustomerDebt extends Component {
constructor(props) {
super(props);
this.domain = `http://127.0.0.1:8000`;
this.state = {
isLoaded: true,
items: [], //Customer Debt Items
};
}
async componentDidMount() {
//customer debt list
await fetch(
`${this.domain}/api/debt/list?customer=` +
this.props.customerInfo.customer.id,
{
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
"Content-Type": "application/json"
}
}
)
.then(res => {
if (res.ok) {
return res.json();
} else {
return res.json().then(err => Promise.reject(err));
}
})
.then(json => {
this.setState({
items: json,
});
this.abortController.abort();
})
.catch(error => {
return error;
});
}
render() {
const { isLoaded, items } = this.state;
if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className={"animated fadeIn container-fluid"}>
<Row>
<Col>
<Card>
<CardHeader>
<i className="fa fa-align-justify" /> Müşteri Borcu
</CardHeader>
<CardBody>
<Table hover bordered striped responsive size="sm">
<thead>
<tr>
<th width={"10"} />
<th width={"15"}>No</th>
<th style={{ display: "none" }}>User</th>
<th style={{ display: "none" }}>Key</th>
<th style={{ display: "none" }}>CreatedUserKey</th>
<th width={"40"}>Total debt</th>
<th width={"40"}>Received amount</th>
<th scope={"row"}>Description</th>
<th width={"20"}>Payment Date</th>
</tr>
</thead>
<tbody>
{items.map(item => {
return (
<tr key={item.id}>
<td>{item.id}</td>
<td style={{ display: "none" }}>{item.user}</td>
<td style={{ display: "none" }}>{item.debtKey}</td>
<td style={{ display: "none" }}> {" "} {item.createduserKey}{" "} </td>
<td>{item.totalDebt}</td>
<td>{item.receivedAmount}</td>
<td>{item.description}</td>
<td> {new Date(item.paymentDate).toLocaleString()} </td>
</tr>
);
})}
</tbody>
</Table>
<nav>
<Pagination>
<PaginationItem>
<PaginationLink previous tag="button">
Back
</PaginationLink>
</PaginationItem>
<PaginationItem active>
<PaginationLink tag="button">1</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink tag="button">2</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink tag="button">3</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink tag="button">4</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink next tag="button">
Next
</PaginationLink>
</PaginationItem>
<PaginationItem></PaginationItem>
</Pagination>
</nav>
</CardBody>
</Card>
</Col>
</Row>
</div>
);
}
}
}
export default CustomerDebt;
您需要根据记录数动态生成分页按钮,然后在按下分页按钮时,设置页码,如果要根据页码和每页大小显示项目,则创建一个数组。
这是示例代码,可让您了解如何完成此操作。这不是完整的或错误证明,因为这是你的工作。我希望能明白。
class CustomerDebt extends Component {
constructor(props) {
super(props);
this.domain = `http://127.0.0.1:8000`;
this.state = {
isLoaded: true,
items: [], //Customer Debt Items,
pageItems: [],
page: 0,
pageSize: 6
};
}
async componentDidMount() {
const { pageSize } = this.state;
//customer debt list
await fetch(
`${this.domain}/api/debt/list?customer=` +
this.props.customerInfo.customer.id,
{
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
"Content-Type": "application/json"
}
}
)
.then(res => {
if (res.ok) {
return res.json();
} else {
return res.json().then(err => Promise.reject(err));
}
})
.then(json => {
this.setState({
items: json,
pageItems: json.slice(0, pageSize)
});
this.abortController.abort();
})
.catch(error => {
return error;
});
}
render() {
const { isLoaded, pageItems, items, page, pageSize } = this.state;
const pages = Math.ceil(items.length / page);
const paginationItems = Array(pages).fill('').map((i, index) => (
<PaginationItem active={page === index}>
<PaginationLink tag="button" onClick={() => this.setState({page: index })}}>2</PaginationLink>
</PaginationItem>
));
if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className={"animated fadeIn container-fluid"}>
<Row>
<Col>
<Card>
<CardHeader>
<i className="fa fa-align-justify" /> Müşteri Borcu
</CardHeader>
<CardBody>
<Table hover bordered striped responsive size="sm">
<thead>
<tr>
<th width={"10"} />
<th width={"15"}>No</th>
<th style={{ display: "none" }}>User</th>
<th style={{ display: "none" }}>Key</th>
<th style={{ display: "none" }}>CreatedUserKey</th>
<th width={"40"}>Total debt</th>
<th width={"40"}>Received amount</th>
<th scope={"row"}>Description</th>
<th width={"20"}>Payment Date</th>
</tr>
</thead>
<tbody>
{pageItems.map(item => {
return (
<tr key={item.id}>
<td>{item.id}</td>
<td style={{ display: "none" }}>{item.user}</td>
<td style={{ display: "none" }}>{item.debtKey}</td>
<td style={{ display: "none" }}> {" "} {item.createduserKey}{" "} </td>
<td>{item.totalDebt}</td>
<td>{item.receivedAmount}</td>
<td>{item.description}</td>
<td> {new Date(item.paymentDate).toLocaleString()} </td>
</tr>
);
})}
</tbody>
</Table>
<nav>
<Pagination>
<PaginationItem onClick={() => this.setState(prev => ({page: prev.page -1}))}>
<PaginationLink>
Back
</PaginationLink>
<PaginationItem onClick={() => this.setState(prev => ({page: prev.page + 1}))}>
<PaginationLink next tag="button">
Next
</PaginationLink>
</PaginationItem>
<PaginationItem></PaginationItem>
</Pagination>
</nav>
</CardBody>
</Card>
</Col>
</Row>
</div>
);
}
}
}
export default CustomerDebt;
首先,您需要创建两个变量来帮助您跟踪当前页面和 table 的大小。我们称它们为 pageSize
和 pageIndex
class App extends React.Component {
state = {
pageSize: 2, // <- 2 items will be shown on single page
pageIndex: 0, // 0 is a default page to show
items: []
};
...
然后您需要从外部源获取一些数据。在我的示例中,我只是创建了一个模拟数组并将其设置为状态。
...
componentDidMount() {
const data = [
{ id: 1, name: "Roman" },
{ id: 2, name: "Oleh" },
{ id: 3, name: "Vitalii" },
{ id: 4, name: "Mikhail" },
{ id: 5, name: "Vladislav" },
{ id: 6, name: "Anton" },
{ id: 7, name: "Yurii" },
{ id: 8, name: "Volodymir" },
{ id: 9, name: "Taras" }
];
this.setState({ items: data });
}
...
之后,您需要创建辅助函数并在其中放置 table 导航逻辑。我们将它们命名为 handlePrevPageClick
和 handleNextPageClick
.
handlePrevPageClick
应该减少点击时的当前索引。此外,我们需要防止用户滚动太多。所以,如果 pageIndex
不为 0 - 减少,否则停止减少。
handleNextPageClick
的逻辑应该和handlePrevPageClick
完全一样。唯一的东西是颠倒的。不要让用户过度滚动您的 table。为此,我们需要了解我们有多少页。通过除以 this.state.items / this.state.pageSize
我们将得到可用页面的总数。假设我们的 table 有 12 个项目,页面大小为 5。因此,12 / 5 = 2.4。这意味着我们将有 2 个页面已满载,还剩下 4 个项目。通过使用 Math.ceil(12 / 5)
我们将得到 3 - 是 table 的可用页面总数的整数。之后,我们只添加简单的条件,如果 pageIndex
< 3,如果是 - 增加 pageIndex
,否则停止。
...
handlePrevPageClick(event) {
this.setState(prevState => ({
pageIndex: prevState.pageIndex > 0 ? prevState.pageIndex - 1 : 0
}));
}
handleNextPageClick(event) {
this.setState(prevState => ({
pageIndex:
prevState.pageIndex <
Math.ceil(prevState.items.length / prevState.pageSize)
? prevState.pageIndex + 1
: prevState.pageIndex
}));
}
最后想到的是用正确的行呈现 table。为此,您可以使用 .slice(...)
。第一个参数是页面的左边界,第二个参数是页面的右边界。
首页
this.state.pageIndex * this.state.pageSize, // 0 * 5 = 0
this.state.pageIndex * this.state.pageSize + this.state.pageSize // 0 * 5 + 5 = 5
显示从索引 0 到 5 的元素。
第二页
this.state.pageIndex * this.state.pageSize, // 1 * 5 = 5
this.state.pageIndex * this.state.pageSize + this.state.pageSize // 1 * 5 + 5 = 10
显示从索引 5 到 10 的元素。
...
render() {
return (
<>
<button onClick={event => this.handlePrevPageClick(event)}>
Prev page
</button>
<button onClick={event => this.handleNextPageClick(event)}>
Next page
</button>
<table border="1">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
</tr>
</thead>
<tbody>
{this.state.items
.slice(
this.state.pageIndex * this.state.pageSize,
this.state.pageIndex * this.state.pageSize + this.state.pageSize
)
.map(item => (
<tr>
<td>{item.id}</td>
<td>{item.name}</td>
</tr>
))}
</tbody>
</table>
</>
);
}
}
如果您想查看完整的工作示例,请使用此 CodeSandbox link