Intersection Observer API / React infinite scroll

DONNIE·2022년 10월 12일
0

React

목록 보기
6/26

드디어 해결이 됐다.

구현할 내용

  • Callback card 10개씩 보여주기
  • 최하단 카드 도달시 서버랑 통신, 새로운 카드 배열에 추가

에로 사항

  • 서버 통신시 paging start number, end number를 전송하는데
    state로 관리함에도 update가 안돼서 계속 이전에 불러온 data를 불러옴
  • Swagger에서 카드 불러올 때, data가 10개가 안되면 2-3개만 받아오는게 됐는데 로컬 구현은 계속 10개로 됨
  • target 설정을 가장 하단에 있는 card에만 해야했기때문에 useRef()는 사용이 어려웠음 (왠진 모름 걍 안됨)

Observer 생성


const [pages, setPages] = useState({
        start:1,
        end:10
    })
const [target, setTarget] = useState(null);
const [isLoading, setIsLoading] = useState(false);
    
    
useEffect(()=>{
        let observer;
        const options = {
          root: null,
          rootMargi: '0px',
          theshold: 1.0
        }
        // pageㄱ ㅏ 1일땐 최초 렌더링에서 처리하므로 중복됨
        if(target && pages.start!==1) {
          const onIntersect = async ([entries], observer) => {
            if(entries.isIntersecting) {
              if(cards.length%10===0) {
                setIsLoading(true) // 로딩바보이기
                observer.unobserve(entries.target);
                await fetchCards();
                observer.observe(entries.target)
                setIsLoading(false) // 로딩바 가리기
              }
              
            }
          }
          observer = new IntersectionObserver(onIntersect, options)
          observer.observe(target);
        }
        return () => observer && observer.disconnect();
      },[target])
      
      
       const fetchCards = async()=> {

            if(pages.start > maxCard) return false;
  
            // await fetch(config.URL_ADDRESS+config.SEARCH_CALLBACK_LIST+'/'+user, {
            await fetch(config.URL_ADDRESS+config.SEARCH_CALLBACK_LIST+'/'+user+'/'+pages.start+'/'+pages.end, {
                mode: 'cors',
                headers: {
                    'Accept':'application/json',
                    'Authorization': 'Bearer ' + accToken,
                  }
            })
            .then (res=>{
                return res.json();
            })
            .then (data=> {
    
                const lists =[];
                const idxs =[];
                let count = 0;
                data.map((d,index)=>(
                    
                    d.modal = false,
                    d.alert = {
                        isClicked : false,
                    }
                    ,
                    d.auto_send === 1 ?
                    setAutoIdx(d.card_id)
                    :
                    null
                    ,
                    d.bookmark === 1
                    ?
                    <>
                    {lists[count]=d.card_id}
                    {count++}
                    {idxs[idndex]=index}
                    </>
                    :
                    null
                ))
                data.sort(function(a,b) {
                    return (b.card_id-a.card_id);
                })
                data.sort(function(a,b) {
                    return (b.auto_send && b.bookmark) - (a.auto_send || a.bookmark);
                })

                setCards(cards.concat(data)); // concat을 prev로 할 때 계속 같은 데이터가 												// 추가됐음
                let tempdata = {lists,count}
                setBookmark(tempdata)
                if(data.length%10===0) { // data가 열개 이하면 추가로 통신할 필요가 없어											// page 값 업데이트할 필요 없음
                    setPages({
                        ...pages,
                        start: pages.start+10,
                        end: pages.end+10
                    })
                }
            })
            .catch((err)=>{
                console.log(err)
               
            })
        }
        
  • html

<div className="list" key={`card`+index} id={card.card_id} ref={setTarget}>
...
</div>
  • 카드 갯수로 불필요한 데이터 통신을 막아야 하므로 카드 갯수 받아오는 통신을 머저 한 후에 cardlist를 fetching 함
useEffect(()=>{
        fetchCards();
    },[maxCard])
profile
후론트엔드 개발자

0개의 댓글