繁体   English   中英

如何使用 Nextjs、Prisma 和 SWR 创建分页表?

[英]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)的行。

抵消

图片来自 Prisma 文档 资料来源:棱镜文档

需要将查询参数发送到 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 )来完成(您将需要实现此逻辑)。 可以有页码; 您需要做的就是使用cursorskip页面之间的行数差异。 (例如,从第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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM