현재 다독다독의 도서 검색 기능은 API에 파라미터로 책의 개수 받아 일정 개수의 도서만 검색이 가능하기 때문에 책 탐색에 한계가 있다.
원하는 책을 찾을 때까지 스크롤을 내리다 뷰포트의 최하단에 닿는 순간 다음 책들을 불러오기 위해 인피니트 스크롤이 필요하다.
useEffect를 사용하여 뷰포트의 최하단에 닿으면 pageNums state값을 ++ 해주면서 API를 다시 호출하는 식으로 구현을 해볼 예정이다. 또한 다독다독의 책 검색 리스트에는 이미지도 포함되어 있기 때문에 트래픽을 최소화하기 위해 img 태그에 lazy load 속성을 추가한다.
첫 번째로 도서 API 호출쪽을 수정했다. isScroll을 파라미터로 받아 true면 불러올 pageNum을 1씩 추가해주면서 API를 재호출하여 기존 books 리스트에 붙여넣고, false면 새로운 검색어를 입력받은 것으로 인식하여 books와 pageNum을 초기화한다.
// 도서API 호출
const FetchBooks = async(keyword, isScroll) =>{
let params = {
query : keyword,
page : pageNum,
}
if (isScroll){
setPageNum(pageNum+1)
params = {...params, page: pageNum}
} else {
setBooks([])
setPageNum(1)
}
const response = await BookService.searchBooks(params)
setBooks([...books, ...response.data.documents])
}
두 번째로는 검색한 도서가 보여지는 컴포넌트인 SearchResult를 수정했다. 스크롤되어 올라간 만큼의 높이(scrollTop) + 현재 보여지는 요소의 높이(clientHeight)이 요소의 전체 높이(scrollHeight)보다 크거나 같으면 뷰포트의 끝에 닿았다고 인식하여 FetchBook을 호출하는 형식이다.
(즉, 스크롤을 내려서 이동한 높이와 요소의 전체 높이가 같아지면 스크롤의 최하단까지 내려왔다고 인식함)
(출처: http://lab.naminsik.com/158)
(출처: https://blogpack.tistory.com/706)
const infiniteScroll = () =>{
const scrollHeight = document.querySelector('.content').scrollHeight
const scrollTop = document.querySelector('.content').scrollTop
const clientHeight = document.querySelector('.content').clientHeight
if (scrollTop + clientHeight >= scrollHeight) {
props.FetchBooks(params.keyword, true)
}
}
useEffect(() => {
document.querySelector('.content').addEventListener('scroll', infiniteScroll)
return () => document.querySelector('.content').removeEventListener('scroll', infiniteScroll)
})
})
LazyLoading은 img 태그에 loading='lazy'를 추가했다. 사파리에서는 작동하지 않는다고 하니 추후에 보완할 예정이다.
<img src={props.book.thumbnail} loading='lazy'></img>