REACT

[React] KUCC 리액트 세션 7. 무한 스크롤[클래스 컴포넌트 ver.]

닉네임이 멋이 중헌디 2021. 5. 19. 01:12

출처: https://velog.io/@hyounglee/TIL-56

 

TIL 56 | React로 무한스크롤 구현

참고 자료 : React에서 Infinite Scroll 구현하기무한스크롤은 화면의 맨 아래까지 스크롤을 하면 새로운 컴포넌트가 랜더되는 형태이다. 페이스북, 인스타그램 등 다양한 사이트가 이러한 무한 스크

velog.io

무한스크롤: 화면의 맨 아래까지 스크롤을 하면 새로운 컴포넌트가 랜더되는 형태이다.

ex. 페이스북, 인스타그램 등

=> 불필요하게 수많은 데이터를 긁어오기보다는, 한번에 10-20개 정도의 포스트만 가져와서 스크롤 될 때마다 업데이트 되는 형식이다.

=> 물론 백엔드에서 정보를 받아와야 구현이 가능하지만 이분은 mock.json을 사용하셨다 

 

[방법 #1. Class Component로 구현하기]

import React from "react";

import List from "../../../Components/List/List";

import Sorting from "../../../Components/Sorting/Sorting";

import "./Allitem.scss";

 

class Allitem extends React.Component {

 constructor( ) {

   super( );

 

 

 this.state = {

       productList: [],

       items: 10,

       preItems: 0,

     };

  }

 

// constructor로 state의 초기값을 정한다. super()로 부모 자식 상속

//state 다시보기

 

componentDidMount() {

  fetch("/Data/mock.json")

     .then((res) => res.json())

//.then은 fetch로 불러오는 정보를 다 가져온 다음에 해당 함수를 수행하기 위해 사용된다

//.json()은 정보를 json형태로 정리해준다 ({key: value},{key: value}...{key: value})형태 

        .then((res) => {

          let result = res.data.slice(this.state.preItems, this.state.items);

//jsonify한 정보 중 data의 value를 state에 갱신되는 preItems, items로 인덱싱해 slice로 자른다 [result : 정보 정리]

          this.setState({

             productList: [...this.state.productList, ...result],

// setState로 state의 값을 경신

   => state의 productList를 ...로 풀은 뒤 ...result로 인덱싱한 정보 배열을 풀고 productList에 붙인다

[mount했을 때 state에 정보 포함]

                });

             });

          window.addEventListener("scroll", this.infiniteScroll, true);

//true는 뭔지 모르겠다

"scroll"하면 infiniteScroll을 실행한다 

}

 

          infiniteScroll = () => {

             let scrollHeight = Math.max(

                  document.documentElement.scrollHeight,

                  document.body.scrollHeight

             );

// document의 element 중 scrollHeight와 body의 scrollHeight 중 더 큰 걸로 선택 

//이건 더 정확한 계산을 위해 하는 방법

   

             let scrollTop = Math.max(

                  document.documentElement.scrollTop,

                  document.body.scrollTop

             );

 

             let clientHeight = document.documentElement.clientHeight;

 

             if (scrollTop + clientHeight >= scrollHeight) {

               this.setState({

                  preItems: this.state.items,

                  items: this.state.items + 10,

               });

 

// setState로 내용 경신(setState는 여러 차례 사용할 수 있구나!) - 이때 preItems, items를 재설정

(그러므로 Mount 안에 정리된 정보인 result를 slice하는 두 인덱스를 10씩 계속 뒤로 움직여준다) 

 

               this.componentDidMount();

//다시 mount하는건가?

=> 이미 render가 한 차례 끝난 뒤 또 수정하거나 실행하고 싶은 함수가 따로 있으면 (ex. 서버요청, setTimeout, setInterval 등) componentDidMount로 event를 가져온다

                 }

               };

               

               render() {

                  const { productList } = this.state;

//state는 context에 저장되어 있는 전역 정보. 그러므로 this로 부를 수 있음

(class만, 함수 component에서는 쓸 수 없음) 

const { productList } => 이건 잘 모르겠음. state의 productList?(아마 그런가보다)

                  return ( <article className="Allitem">

                     <div className="topInfo">

                        <div className="totalItems">

                            <p className="totalNum">

                                   총 <span className="pointSpan">1541</span> 개의 상품이 조회되었습니다.

                            </p>

                        </div>

                        <Sorting />

                       </div>

                       <List productList={productList} />

//List Component는 imported from another file

//List의 props = productList가 있나보다. 그 곳에 위에 선언한 const {productList}(state에서 정의한 productList(json으로 정리한 정보인 result를 preItems, Items로 slice한 결과물)를 대입할 수 있다.

    => 아무튼 결국에는 scrollTop + clientHeight가 scrollHieght보다 커질 때 List component를 통해서 productList의 새로운 정보를 10씩 가져온다

                      </article>

                      );

                   }

               }

           

              export default Allitem;

 

 

scrollHeight <= clientHeight(client에게 보이는 화면)+ scrollTop(전체 scrollHeight 중 스크롤을 내린만큼)

: 제공한 정보가 모두 보여졌으므로 새로운 getData 요청을 해야한다