무한 스크롤 구현(React, Javascript)

juno·2022년 8월 22일
0

React

목록 보기
1/5

바닐라 자바스크립트로 무한 스크롤 구현하고, React 라이브러리를 사용하여 응용해본 경험을 풀어 보았다.

바닐라 자바스크립트

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>한무스크롤</title>
    <style>
        html, body{ margin: 0;}
        section .box{
            height: 500px; background: tomato; color: white;
            box-sizing: border-box; padding: 30px 10px;
        }
        section .box:nth-child(2n) { background: teal;}
    </style>
</head>
<body>
    <section>
        <div class="box">1번째 블록</div>
        <div class="box">2번째 블록</div>
    </section>
    <script>
        let count = 2;
        window.onscroll = () => {
            if((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
                const toAdd = document.createElement('div');
                toAdd.classList.add('box')
                toAdd.textContent = `${++count}번째 블록`
                document.querySelector('section').appendChild(toAdd);
            }
        }
    </script>
</body>
</html>

편의상 전체 코드를 붙여 놨습니다.

핵심 포인트

(window.innerHeight + window.scrollY) >= document.body.offsetHeight)

사실 상 위의 코드만 이해하면 내 것으로 만들 수 있습니다.

  • window.innerHeight = 현재 이 글을 보고있는 사용자의 창 높이
    (개발자도구를 열어서 콘솔에 'document' 만 쳤을 때, 선택되는 부분의 높이!!)
    본인의 현재창이 1000px일수도 500px일 수도 있습니다.

  • window.scrollY = 현재 스크롤의 Y
    (제일 상단의 Y 입니다. 이것도 현재 창의 크기에따라 값이 다릅니다.)

    위 두가지는 모니터의 크기에따라 다르게 나옵니다. 직접 개발자 도구를 열어서 눈으로 확인해 보세요.

    아니면 이해가 안됨..

  • document.body.offsetHeight = body의 최상단에서 최하단까지의 높이값
    (맨위부터 맨아래까지의 거리)

결론

window.innerHeight + window.scrollY = document.body.offsetHeight 입니다.

이벤트를 끄고, 위에 코드 기준 스크롤을 제일 아래로 내렸을 때

무한스크롤 발동 조건

window.innerHeight + window.scrollY >= document.body.offsetHeight

스크롤을 내릴때 마다 계속 변하는 window.scrollY의 변동에 따라 위의 조건을 만족 할때,

                toAdd.classList.add('box')
                toAdd.textContent = `${++count}번째 블록`
                document.querySelector('section').appendChild(toAdd);

위의 태그를 추가한다.

React 에서 사용하기

구현 방법

window.innerHeight + window.scrollY >= document.body.offsetHeight

위의 조건이 만족 했을때, fetch 메서드로 데이터를 추가로 가져오고, useState로 hook을 일으켜서, 추가 렌더링을 한다.

import { useEffect, useState } from 'react';

const InfiniteScroll = () => {
    const [feed,setFeed] = useState([])

    const onScroll = () => {
        if(window.innerHeight + window.scrollY >= document.body.offsetHeight) {
            console.log(1)
            fetch('data/infinit.json')
            .then(response=> response.json())
            .then(data=> setFeed([...feed,...data]))
        }
    }

    useEffect(
        ()=>
            fetch('data/infinit.json')
                .then(response=>response.json())
                .then(setFeed),
        []
    )


    useEffect(()=> {
        window.addEventListener('scroll',onScroll);
        return () =>window.removeEventListener('scroll',onscroll)
    })

    return feed.map(img => <img key={img.id} src={img.img} alt={img.id}/>)

}

export default InfiniteScroll

코드 전체를 가져오면 난잡해져서 일부분만 가져왔습니다.

무한스크롤 github

여기서 핵심은 스크롤이 최하단으로 갈때마다, setFeed로 data를 누적시키면서 hook을 일으켜서,
리렌더링이 되는 것입니다.

profile
안녕하세요 인터랙션한 웹 개발을 지향하는 프론트엔드 개발자 입니다. https://kimjunho97.tistory.com => 블로그 이전 중

0개의 댓글