[分享] 實作 Lazy Loading 與向下滾動以載入更多 (react-infinite-scroll-component)

Y000ga
6 min readJan 10, 2023

--

Rent Helper 網站使用 Lazy Loading 顯示物件清單

Rent Helper 租屋小幫手 專案中需要大量載入使用者所收藏的物件圖片與資料,這時候就適合使用 Lazy Loading(延遲載入)的技巧,可提升頁面載入速度,也能節省 client 端和 server 端間網路流量,以下將應用第三方套件 react-infinite-scroll-componenet 達到 Lazy Loading 的效果。

// CollectPage.jsx
import InfiniteScroll from 'react-infinite-scroll-component'

// ...

const CollectPage = () => {
const allRoom = useSelector((state) => state.room.allRoom) // 所有物件的資訊
const [page, setPage] = useState(1) // Lazy Loading 的顯示頁數,預設顯示第一頁
const [hasMore, setHasMore] = useState(true) // 是否後續還有資料,預設為 true

// ...

useEffect(() => {
const housesAllGet = async () => {
const res = await housesAllGetApi({ page: 1 })
// 一進入頁面就打 API 獲得第一頁的資料
const { houses } = res.data
dispatch(roomActions.getAllHouses(houses))
setPage(2) // Lazy Loading 的顯示頁數 (page) 改為第二頁
}
// ...
}, [dispatch])

const roomList = allRoom.map((data) => <RoomItem data={data} key={data.id} />)

// ...

// 當要進入下一頁會觸發
const changePage = async () => {
const res = await housesAllGetApi({ page: page })
// 打 API 獲得下一頁物件資訊
const { houses } = res.data
setHasMore(houses.length) // 將 hasMore 設為下一頁物件總量
// ...
setPage((page) => page + 1)
// Lazy Loading 的顯示頁數 (page) 改為當前頁數的下一頁
}

return (
<LayoutWrapper>
<div className={classes.container}>
{/*...*/}
<div className={classes.roomItemContainer} id='room__list'>
{allRoom.length === 0 ? (
{/*...*/}
) : (
<InfiniteScroll
className={classes.infiniteScroll}
dataLength={allRoom.length}
// 透過 dataLength 是否變化
// 確認是否 render 因 next props (trigger changePage) 而得到的 data

next={changePage}
// next prop 所設定的 func. changePage 用於獲得下一頁的資

hasMore={hasMore !== 0}
// hasMore prop 為 false 時不會觸發 next prop 所指向 func.
// 當打 API 所獲得的資料為零,hasMore (state variable) 也為零

loader={
<div className={classes.loadingContainer}>
<Loop
className={classes.loading}
sx={{ cursor: 'wait', fontSize: '54px' }}
color='success'
/>
</div>
}
// 等待下一頁資料時,出現Loading Icon 提示 user 資訊即將出現

endMessage={null}
scrollableTarget='room__list'
height={850}
>
{roomList}
</InfiniteScroll>
)}
</div>
</div>
</LayoutWrapper>
)
}

export default CollectPage

以上 Lazy Loading 載入新資訊的觸發順序可以整理如下:

  1. 剛進入頁面時,第一次打 API 獲得第一頁物件資料們,為了等一下要拿第二頁物件資料們,先透過 setter func. setPage 將 page 設定為 2。
  2. 使用者往下滑的時候,由於 hasMore 的初始值為 true,所以必定會觸發 next prop 所指向的 func. (changePage),打 API 取得第二頁的物件資料們。
  3. 透過 API 回傳的 response (內含第二頁物件資料們 houses ),使用 setter func. setHasMore 將 hasMore 設定 houses.length,
  4. 如果第二頁物件資料們為 0 則 hasMore props 為 false,代表 allRoom.length (總物件資料數量) 不變,也不會去試圖 render。
  5. 如果第二頁物件資料們不為 0 則 hasMore props 為 true,allRoom.length 增加,dataLength props 改變就會去 render 新資料
  6. 為了等一下要拿下一頁物件資料們,先透過 setter func. setPage 將 page 設定為當前頁面 + 1。
  7. 後續重複第 2 ~ 6 步驟。

作為支援 React 的 UI Library Ant Design,也有將 List 結合 react-infinite-scroll-componenet 的 Scrolling loaded List Component,以後也想嘗試應用。

--

--

Y000ga

喜歡穿環、滑板、植物和閱讀的射手女子,在學習前端的路上邊走邊跳邊跌倒,人生清單超長一串,覺得挫折的時候就用力用力撸貓 ฅ•ω•ฅ