React Query 的 useQuery 竟也内置了分页查询支持!

开发 前端
本文我讲解了另一个 useQuery() 能力——keepPreviousData。在设置 keepPreviousData: true 后,我们在进行分页查询时,同时能保持旧数据的展示,避免页面闪动。

本次我们将继续 useQuery() API 的学习,着重讲述 useQuery() 在分页上的优化能力[3]。

基本分页功能实现

项目中通常会遇到分页查询的需要,通过之前的学习,我们会写出这样的代码。

function Example() {
  const [page, setPage] = useState(1)

  const { isLoading, isError, error, data: posts } = useQuery(
    ['posts', page],
    () => axios.get('https://jsonplaceholder.typicode.com/posts', { params: { _page: page, _limit: 6 } })
  )

  return (
    <div>
      <h2>Posts(第{page}页)</h2>
      {
        isLoading && <p>Loading....</p>
      }
      {
        isError && <p>An error has occurred: {error.message}</p>
      }
      <ul>
        {
          posts?.data.map(post => (
            <li key={post.id}>{post.title}</li>
          ))
        }
      </ul>
      <div style={{ display: 'flex', gap: '8px' }}>
        <button disabled={isLoading} onClick={() => setPage(prePage => Math.max(0, prePage - 1))}>Previous Page</button>
        <button disabled={isLoading} onClick={() => setPage(prePage => prePage + 1)}>Next Page</button>
      </div>
    </div>
  )
}

浏览器访问:

图片图片

点击“Next Page”查看下一页数据。

图片图片

确实也实现了功能,不过体验上不好的地方在于,每次切换到新一页数据时,中间会间隔一个“Loading...”效果,导致页面闪动。

为了不然页面闪动,我们可以考虑在加载新页面数据时,同时保留旧数据的展示不就行了吗?后面一旦新数据到了,直接替换就行。

useQuery() API 可考虑到了这方面的使用体验,于是便提供了一个 keepPreviousData 选项。

保留旧数据的分页功能

我们在之前案例的基础之上,调用 useQuery() 时,指定 keepPreviousData: true 选项。

const { isLoading, isError, error, data: posts } = useQuery(
  ['posts', page],
  () => axios.get('https://jsonplaceholder.typicode.com/posts', { params: { _page: page, _limit: 6 } }),
  {
    keepPreviousData: true
  }
)

刷新页面,再来看看加载新页的效果。

图片图片

发现页面不再闪动了。

不过,这种状态下的中间状态我们还要细致的控制一下,比如请求过程中禁用按钮的点击能力。

- const { isLoading, isError, error, data: posts } = useQuery()
+ const { isLoading, isError, isFetching, error, data: posts } = useQuery()

<div style={{ display: 'flex', gap: '8px' }}>
-  <button disabled={isLoading} notallow={() => setPage(prePage => Math.max(0, prePage - 1))}>Previous Page</button>
-  <button disabled={isLoading} notallow={() => setPage(prePage => prePage + 1)}>Next Page</button>
+  <button disabled={isLoading || isFetching} notallow={() => setPage(prePage => Math.max(0, prePage - 1))}>Previous Page</button>
+  <button disabled={isLoading || isFetching} notallow={() => setPage(prePage => prePage + 1)}>Next Page</button>
</div>

再次查看效果:

图片图片

不过,除了 isFetching,useQuery() 还返回了一个 isPreviousData 状态,让你判断当前展示的是不是旧数据。

- const { isLoading, isError, isFetching, error, data: posts } = useQuery()
+ const { isLoading, isError, isPreviousData, isFetching, error, data: posts } = useQuery()


- <ul>
+ <ul style={{ opacity: isPreviousData ? 0.5 : 1 }}>
  {
    posts?.data.map(post => (
      <li key={post.id}>{post.title}</li>
    ))
  }
</ul>

再次查看效果:

图片图片

这样旧数据在展示期间,加了一点点透明效果。

至此,我们就讲完了 useQuery() 的分页优化能力。

总结

本文我讲解了另一个 useQuery() 能力——keepPreviousData。

在设置 keepPreviousData: true 后,我们在进行分页查询时,同时能保持旧数据的展示,避免页面闪动。

本质上,keepPreviousData 选项是 useQuery() 针对分页场景上的一个优化能力。

当然,UI 交互中还有一种特殊的分页场景,即无限查询(Infinite Query)。这在“上滑/上拉查看历史数据”,或者“下滑/下拉查看最新数据”被广泛采用,不过 useQuery 是解决不了的了,这要靠 useInfiniteQuery()。

参考资料

[1]React Query 是做什么的?: https://juejin.cn/post/7378015213348257855

[2]一个数据获竟然被 React Query 玩出这么多花样来!: https://juejin.cn/post/7380342160581918731

[3]useQuery() 在分页上的优化能力: https://tanstack.com/query/v3/docs/framework/react/guides/paginated-queries

责任编辑:武晓燕 来源: 写代码的宝哥
相关推荐

2023-05-26 06:30:56

2009-06-18 09:47:50

2022-06-17 08:37:14

分布式事务分库分表

2010-11-25 14:21:16

MySQL查询分页

2016-07-12 09:40:30

恶意程序TLS加密恶意流量

2010-09-26 15:29:13

sql查询分页

2009-07-20 16:18:54

iBatis分页Hibernate式的

2017-05-15 15:54:50

MySQL数据库

2010-11-18 13:32:12

Oracle分页查询

2024-06-11 09:02:30

2024-07-02 10:00:55

2024-10-14 08:39:25

2024-11-04 09:43:00

模型训练

2016-12-05 13:53:23

2011-04-06 10:25:52

Windows 8

2020-11-25 15:52:59

SQL工具数据

2010-09-07 10:35:38

SQL语句

2010-05-04 15:15:39

Oracle分页查询

2009-09-21 13:42:47

Hibernate查询

2009-04-09 13:14:09

Oracle分页查询CBO
点赞
收藏

51CTO技术栈公众号