ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • React/InfiniteScroll - 내부 collection
    Language/React 2022. 12. 2. 09:47

     

    InfiniteScroll을 공통으로 사용하기 위해서 Component형식으로 만들고 나중을 위해서 정리해 둔다.

    InfiniteScroll Component 내부에 collection을 두고 사용하는 방식

     

    부모 컴퍼넌트

    import React, { Component } from 'react';
    ...
    
    class RequestViews extends Component {
      state = {
        infiniteResetUseEffect: false, // Infinite 외부에서 리스트를 초기화 해줘야 할 경우 변경
        requests: [],
        ...
      };
    
      fetchMoreList = (offset) => {
        return new Promise((resolve, reject) => {
          const pagination = { ...this.pagination, offset };
    
          const params = { pagination: pagination, filters: this.filters };
          Request.get('/requests?' + JSON.stringify(params)).then((response) => {
            resolve(response.DATA);
          });
        });
      };
    
      resetList = () => {
        this.setState({ resetInfiniteUseEffectFlag: !this.state.resetInfiniteUseEffectFlag });
      };
      
      ...
    
      render() {
        const { requests } = this.state;
    
        if (!requests) {
          return false;
        }
    
        return (
          <>
            <div className="inner-content box-list-wrap">
              ...
    
              <>
                <InfiniteScroll
                  fetchMoreList={this.fetchMoreList}
                  infiniteResetUseEffect={this.state.infiniteResetUseEffect}
                  getTemplate={(items) => {
                    console.log('getTemplate items : ', items);
                    return (
                      <>
                        <div className="items-wrap">
                          <ul>
                            {items.map((request, idx) => (
                              <li className="box" key={request.G_REQUEST_NO}>
                                <RequestView
                                  request={request}
                                  onRequestViewPop={(request) => {
                                    this.setState({ visibleRequestViewPop: true, request: request });
                                  }}
                                  handleChangeStatus={(request) => {
                                    this.handleChangeStatus(request);
                                  }}
                                />
                              </li>
                            ))}
                          </ul>
                        </div>
                      </>
                    );
                  }}
                >
                </InfiniteScroll>
              </>
            </div>
    
            <RequestViewPop
              open={this.state.visibleRequestViewPop}
              gRequestNo={this.state.request?.G_REQUEST_NO}
              onClose={() => this.setState({ visibleRequestViewPop: false, request: null })}
              onUpdate={() => {
                this.props.onUpdate();            
                this.resetList();
              }}
            />
            ...
          </>
        );
      }
    }
    
    export default wrapWithBase(RequestViews);

     

    자식 컴포넌트

    import React, { useEffect, useState } from 'react';
    
    const InfiniteScroll = (props) => {
      const [items, setItems] = useState([]); // 보여줄 전체 리스트
      const [offset, setOffset] = useState(0); // back에 요청할 페이지 데이터 순서 정보
      const [target, setTarget] = useState(null); // 관찰대상 target
      const [isLoaded, setIsLoaded] = useState(false); // Load 중인가를 판별 (요청이 여러번 가는 것을 방지)
      const [stop, setStop] = useState(false); // 마지막 데이터까지 다 불러온 경우 더이상 요청을 보내지 않기 위해서
    
      useEffect(() => {
        // console.log('마운트 될 때만 실행');
        fetchMorderList();
      }, []);
    
      // React Hooks: componentWillReceiveProps
      // props.infiniteResetUseEffect 변할 때 실행
      useEffect(() => {
        // 초기화
        setItems([]);
        setOffset(0);
        setIsLoaded(false);
        setStop(false);
      }, [props.infiniteResetUseEffect]);
    
      useEffect(() => {
        let observer;
        if (target && !stop) {
          // callback 함수로 onIntersect를 지정
          observer = new IntersectionObserver(onIntersect, {
            threshold: 1,
          });
          observer.observe(target);
        }
        return () => observer && observer.disconnect();
      }, [target, isLoaded]);
    
      // isLoaded가 변할 때 실행
      useEffect(() => {
        // isLoaded가 true일 때 + 마지막 페이지가 아닌 경우 = 요청보내기
        if (isLoaded && !stop) {
          fetchMorderList();
        }
      }, [isLoaded]);
    
    
      const fetchMorderList = async () => {
    	const list = await props.fetchMoreList(offset);
        setItems((items) => items.concat(list));
    
        // 다음 요청할 데이터 offset 정보
        setOffset((offset) => offset + list.length);
    
        // 다음 요청 전까지 요청 그만 보내도록 false로 변경
        setIsLoaded(false);
    
        if (list.length < 3) {
          // 전체 데이터를 다 불러온 경우(불러온 값이 12개 보다 적다면 -> 매번 12개씩 불러오기로 했으므로 해당 값보다 작으면 마지막 페이지) 아예 로드를 중지
          setStop(true);
        }
      };
    
      // callback
      const onIntersect = async ([entry], observer) => {
        // entry 요소가 교차되거나 Load중이 아니면
        if (entry.isIntersecting && !isLoaded) {
          // 관찰은 일단 멈추고
          observer.unobserve(entry.target);
    
          // 데이터를 받아오도록 true 로 변경
          setIsLoaded(true);
    
          // 불러온 후 다시 관찰 실행
          observer.observe(entry.target);
        }
      };
    
      return (
        <>
          {/* <div>
            {items.map((item, index) => (
              <div key={index}>
                {index + 1} / {item.GUEST_NAME}
              </div>
            ))}
            <div ref={setTarget}></div>
          </div> */}
    
          {props.getTemplate(items)}
          <div ref={setTarget}></div>
        </>
      );
    };
    
    export default InfiniteScroll;

     

    참조)

    https://velog.io/@ohsg97/React-infinite-scroll

     

    [React] infinite scroll을 구현해보자

    IntersectionObserver를 이용하여 React에서 Infinite Scroll 구현하기

    velog.io

     

    'Language > React' 카테고리의 다른 글

    React Loop 모음  (0) 2023.05.11
    React/InfiniteScroll - 외부 collection  (0) 2022.12.02
    React/RadioButton Component 만들기  (0) 2022.12.01
    React/X-Bar chart 만들기  (0) 2022.12.01
    React/DropdownSearch 만들기  (0) 2022.12.01

    댓글

Designed by Tistory.