-
React/InfiniteScroll - 내부 collectionLanguage/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
'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