本次我們將繼續 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
本文鏈接:http://www.tebozhan.com/showinfo-26-96988-0.htmlReact Query 的 useQuery 竟也內置了分頁查詢支持!
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com