무한스크롤 구현시 onScroll
💡 scroll event를 보며 페이지가 끝에 오는지 판단하는 방법Intersection Observer API
타겟과 viewport 사이의 intersection 변화를 비동기적으로 관찰하는 방법
등에 사용됨
Intersection Observer API를 사용하는 이유
debounce
& throttle
을 사용하지 않아도 됩니다..offsetTop
값을 구할 때 는 정확한 값을 구하기 위해서 매번 layout을 새로 그리는데 이를 Reflow라 합니다. Intersection Observer를 사용하면 Reflow를 하지 않습니다.react-intersection-observer 라이브러리
npm i react-intersection-observer
사용 방법
import React from "react"
import { useInView } from "react-intersection-observer"
const App = () => {
const [ref, inView] = useInView()
return (
<div ref={ref}>
Element {inView.toString()}
</div>
)
}
export default App
ref
를 div에 걸어주면 해당 요소가 보이면 inView가 true
로, 안 보이면 false
로 자동으로 변경됩니다.
import { useInView } from 'react-intersection-observer'
const [ref, inView] = useInView()
useEffect(() => {
if (inView) setPageNumber((prev) => prev + 1)
}, [inView])
searchMovieList.map((movie, idx) => (
<React.Fragment key={movie.imdbID}>
{searchMovieList.length - 1 === idx ? (
<div ref={ref}>
<MovieCard
title={movie.title}
year={movie.year}
imdbID={movie.imdbID}
type={movie.type}
poster={movie.poster}
/>
</div>
) : (
<MovieCard
title={movie.title}
year={movie.year}
imdbID={movie.imdbID}
type={movie.type}
poster={movie.poster}
/>
)}
</React.Fragment>
))
git의 파일,폴더명의 대소문자 변경 추적
git config core.ignorecase false
설정 이후 커밋하기전에 아래 명령어 실행 후 하는것을 권장
git rm -r --cached .
npm install lodash
기업 과제로 준 api가 굉장히 별로라서,, 중복된 아이디를 가지고 있는 요소를 제거하기 위해 lodash의 uniqBy()를 사용하기 위해 설치했다
import * as _ from 'lodash'
const newList = _.uniqBy(arr, 'key')
key를 기준으로 arr의 요소들의 중복을 제거해준다.
로직이 꼬인 작업이 하나 있었다
searchInput (index.tsx)
// pageNumber = recoil value
useEffect(() => {
if (pageNumber !== 0) {
//api 불러오는 함수
callApi(searchWord, pageNumber)
}
}, [pageNumber])
//...
function callApi(word: string, page: number) {
moviesApi.searchMovielist(word, page).then((res) => {
const success = res.data.Response.toLowerCase()
if (success !== 'false') {
const totalResultCnt = Number(res.data.totalResults)
const lastPage = Math.ceil(totalResultCnt / DATA_COUNT)
setSearchList(res.data.Search)
setAdditionalData({ totalResults: totalResultCnt, lastPageNumber: lastPage })
} else {
resetSeachList()
}
})
}
search (index.tsx)
useEffect(() => {
if (pageNumber !== FIRST_PAGE) {
callMoreApiData(pageNumber)
}
}, [pageNumber])
// 무한 스크롤 (가장 마지막 엘리먼트 보고있을때 페이지 값 증가)
useEffect(() => {
if (inView) setPageNumber((prev) => prev + 1)
}, [inView])
//api 실행 함수
function callMoreApiData(page: number) {
moviesApi.searchMovielist(currentWord, page).then((res) => {
const dataList = res.data.Search
if (dataList !== undefined) {
setSearchMovieList((prev) => [...prev, ...dataList])
}
})
}
이 과정에서 의도된대로 동작이 안했던 이유가 1번의 조건을 제대로 안걸어줬기 때문에
3번 과정에서 pageNumber가 변환이 되니까 searchInput의 useEffect에서도 페이지 변화를 감지했고
if문에 들어가게되어 (0이 아니므로)
setSearchMovieList((prev) => [...prev, ...dataList])
를 제대로 작성해줬음에도 불구하고 이전의 값들이 날아가게 되는 현상이 발생했던 것