[英]How to create a paginated table using Nextjs, Prisma and SWR?
我正在尝试使用 Nextjs、Prisma 和 SWR 创建一个分页表。 该表将显示按 ID 排序的发票列表。 这是它的外观示例:
我正在使用Prisma将所有数据获取到 api 路由和SWR以在 UI 上显示数据并重新验证。这是迄今为止 UI 的代码:
{InvoiceData.map((invoice, key) => {
return (
<tr key={key}>
<td className="font-medium">
#
{invoice.nro_factura &&
Number(invoice.nro_factura).toString()}
</td>
<td className="whitespace-pre-wrap">
{invoice.fecha_emision &&
moment(invoice.fecha_emision).format("MMM DD, YYYY")}
</td>
<td className="font-medium">
${invoice.total && Number(invoice.total).toLocaleString()}
</td>
<td>
<Badge
status={
invoice.total === invoice.pagos
? 0
: invoice.anulada
? 2
: 1
}
title={
invoice.total === invoice.pagos
? "Pagado"
: invoice.anulada
? "Borrada"
: "Pendiente"
}
/>
</td>
<td className="customer-column">
{CustomersData.map((customer) => {
if (customer.cliente_id === invoice.cliente_id) {
return customer.nombre_clte;
}
return null;
})}
</td>
</tr>
);
})}
这是 api 路由中的代码:
import { prisma } from "../../../prisma/index.ts";
export default async function getInvoicesData(req, res) {
let InvoiceData = await prisma.factura.findMany({
orderBy: {
nro_factura: "desc",
},
});
return res.status(200).json(InvoiceData);
}
分页有两种类型:偏移量和游标。 偏移分页通过在跳过某个数字后获取行来工作。 游标分页通过对行进行排序,然后获取游标属性(即 ID)大于传递的游标值(即前端最后一行的 ID)的行。
抵消
需要将查询参数发送到 API 路由,例如page
。 该参数可以表示表格底部的页码。 将此负 1 ( page - 1
) 乘以每页的结果数 ( (page - 1) * size
)。 通过 Prisma 将其作为skip
发送到数据库。 这将跳过表的前 X 行。 您还必须包含take
参数,否则您将提取表的所有结果,不包括skip
之前的行。
一个例子:
const results = await prisma.post.findMany({
skip: 10, // How many rows to skip
take: 10, // Page size
})
然后,您的 API 查询可能如下所示: https://example.com/api/invoices?page=2
。 如果您的页面大小为10
,则第2
页的行“编号”为11-20
(跳过(2 - 1) * 10 = 10
( (page - 1) * size
))。
但是,他的行数可能会变慢。 另一种方法是光标分页(见下文)
光标
这将需要按 ID 排序的查询。 您仍然需要获取一定数量的行(即 10),并将最后一项的 ID 作为游标传递(对于第 2 页及以上):
const firstQueryResults = await prisma.post.findMany({
take: 10, // Page size
skip: 1, // Skip the cursor row
cursor: {
id: myCursor, // The cursor - only on pages 2 and above
},
orderBy: {
id: 'asc', // Ordering results
},
})
这将获取 ID 大于光标的所有行(即myCursor
)
在 API 请求中使用cursor
等查询参数来设置游标。
光标分页要快得多,但是需要排序。 也可以按时间戳排序。 然后,您只需要按查询中的时间戳进行排序。
前端
然后,您可以在前端使用 API 响应中的数据更新存储结果的变量。 我建议您在 API 响应中包含一个带有行数的属性(来自 Prisma 的count
),以便您可以除以页码并在表格底部显示正确的按钮数。
对于偏移分页,当点击按钮时,将页码作为查询参数发送给 API。
对于光标分页,只需有一个下一步和后退按钮就更容易了。 对于下一个按钮,通过发送光标进行分页。 反过来,取负数的行(即-10
) - 这可以通过设置另一个查询参数(例如direction
)来完成(您将需要实现此逻辑)。 可以有页码; 您需要做的就是使用cursor
并skip
页面之间的行数差异。 (例如,从第2页到第5页跳过第3页。因此,您需要使用第2页最后一项的光标,并跳过第3页和第4页的结果数(即20))
根据 SWR 文档,您可以创建一个传递给页面 API 查询的变量。 这可以修改为光标和方向。
function App () {
const [pageIndex, setPageIndex] = useState(0);
// The API URL includes the page index, which is a React state.
const { data } = useSWR(`/api/data?page=${pageIndex}`, fetcher);
// ... handle loading and error states
return <div>
{data.map(item => <div key={item.id}>{item.name}</div>)}
<button onClick={() => setPageIndex(pageIndex - 1)}>Previous</button>
<button onClick={() => setPageIndex(pageIndex + 1)}>Next</button>
</div>
}
其他改进
您可以通过将其作为查询参数发送来动态设置限制或页面大小
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.