Remix 开发小技巧

本文介绍了如何在Remix应用中处理请求搜索参数重定向、服务器端分页,包括从URL读取查询参数、使用AbortSignal控制异步调用,以及使用TypeScript的全局类型提升代码安全性和类型提示。

请求搜索参数重定向

假设您要确保始终设置特定的搜索参数。为此,您可以首先检查是否设置了搜索参数,如果没有,则重定向到设置了搜索参数的同一路由。

export async function loader({
   
    request }: LoaderFunctionArgs) {
   
   
  let url = new URL(request.url);

  if (!url.searchParams.has("key")) {
   
   
    url.searchParams.set("key", "value");
    throw redirect(url.toString());
  }

  // the rest of your code
}

首先,我们创建一个 URL 实例,这使我们能够更轻松地使用 URL。

然后我们访问 URLSearchParams 实例 url.searchParams 并检查它是否没有我们的密钥。如果没有,我们将其设置为 url.searchParams.set(“key”, “value”) .

最后,我们使用新 URL 抛出重定向。这会将用户重定向到相同的路由,但设置了搜索参数。

如果请求 URL 已设置搜索参数,则加载程序将继续执行代码的其余部分。

进行服务器端分页

开发人员通常将客户端分页作为折衷措施实现,以避免服务器端分页的复杂性。

在服务器上处理分页时,需要将特定的页面和页面大小传达给服务器,并且需要返回项总数,以便客户端可以呈现分页控件。

随着页面的更改,您需要更新 URL 并创建新的历史记录条目,以便用户可以使用后退按钮转到上一页,并与其他用户共享特定页面。

然后是数据获取问题:每次页面更改时,您都需要从服务器获取新数据并将其呈现在页面上。

但Remix就是为这种事情而构建的。

为每个 URL 显示正确的数据是 Remix 的目的,因此使用 Remix 实现服务器端分页实际上比在客户端上实现分页更容易。

如果您将页码和大小存储在 URL 中,Remix 将获取新数据并在 URL 更改时立即显示在页面上,并且由于数据库通常有办法一次返回一页数据,因此您也可以免费获得。

从 URL 读取查询参数

OData 规范规定,应使用 和 查询参数分别指定页面大小 $top$skip 页码。

因此,如果要显示 10 个项目的第一页,请使用 ?$top=10 ,而要显示第二页,请使用 ?$top=10&$skip=10

从加载程序中的请求 URL 读取查询参数,并使用它们从数据库中获取正确的数据页。

根据您的数据库适配器,这部分看起来会有所不同,但通常有一种一流的方法可以做到这一点,例如 Prisma 的选项 { take, skip } 或 SQL 和 LIMIT OFFSET 子句。

export async function loader({
   
    request }: LoaderArgs) {
   
   
  const url = new URL(request.url)
  const $top = Number(url.searchParams.get("$top")) || 10
  const $skip = Number(url.searchParams.get("$skip")) || 0
  // Slice the current page of issues from the database
  const issues = db.issues.slice($skip, $skip + $top)
  return json({
   
   
    total: db.issues.length,
    issues,
  })
}

让我们创建一个滚动分页组件,显示当前页面以及它之前和之后的几个页面,就像 Google 搜索一样。

在这里插入图片描述

关于此实现,有几点需要注意

  • 选择第一页时,上一页按钮被禁用,并在当前页面右侧显示 6 页
  • 选择最后一页时,下一页按钮将被禁用,并在当前页面左侧显示 6 页
  • 当当前页面位于中间时,它向左显示 3 页,向右显示 3 页

由于组件可以独立访问 URL 参数,因此我们不需要任何回调或状态管理即可完成此操作。每个按钮都只是一个表单中的提交按钮,用于将 $skip 参数设置为正确的值。

我们需要传递给组件的一个值是项目总数,因此它可以计算总页数。

export function PaginationBar({
   
   
  total,
}: {
   
   
  total: number
}) {
   
   
  const [searchParams] = useSearchParams()
  const $skip = Number(searchParams.get("$skip")) || 0
  const $top = Number(searchParams.get("$top")) || 10
  const totalPages = Math.ceil(total / $top)
  const currentPage = Math.floor($skip / $top) + 1
  const maxPages = 7
  const halfMaxPages = Math.floor(maxPages / 2)
  const canPageBackwards = $skip > 0
  const canPageForwards = $skip + $top < total
  const pageNumbers = [] as Array<number>
  if (totalPages <= maxPages) {
   
   
    for (let i = 1; i <= totalPages; i++) {
   
   
      pageNumbers.push(i)
    }
  } else {
   
   
    let startPage = currentPage - halfMaxPages
    let endPage =
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Willin 老王躺平不摆烂

感谢你这么好看还这么慷慨

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值