본문 바로가기
React

React(95) 리스트 더보기 기능 구현

by 새발개발JA 2023. 4. 25.
반응형

 

 

오늘은 리스트 더보기 기능을 구현해보자

 

맨 처음에 아이템이 다섯 개만 보이는 리스트가 있다.

[더보기] 버튼을 누르면 그 다음 5개를 더 불려오고

마지막 리스트가 나올 때까지 다섯 개씩 불려온다.

 

 

다 불러오게 되면 [접기] 버튼이 나오고 맨 처음 5개만 보이는 초기상태로 돌아가게 된다.

 

 

이것을 구현하기 위해서는 두가지 방법이 있다.

1. 더보기를 누를때마다 getList api 를 호출하여 부분적으로 받아오는 방법이 있고,
2. 처음에 getList api 를 호출하여 한꺼번에 받아온 배열을 프론트에서 보여주는 방법이다.

 

 

각각에 맞는 방법이 있겠지만, 나는 1번을 더 선호한다.

처음에 한꺼번에 전체 배열을 불러온다면 메모리를 그만큼 차지하게 되고, 만약 몇 만 건있는 데이터 배열이라면 과부하가 걸릴 수 있기 때문이고 전체를 다 열람하지 않는 이상 리소스 낭비를 초래하게 된다. (요즘 항상 최악의 상황을 가정하며 개발을 하는 것 같다.)

 

 


React(95) 리스트 더보기 기능 구현

 

1 번의 방법으로 진행해보자

서버 api 에 query params 으로 페이지 정보를 보내면 그에 맞는 데이터를 보내 준다고 가정해보았다.

 

일단 준비물로 리스트 값을 넣을 변수와 페이지 설정에 필요한 변수를 마련해보았다.

또한 현재 페이지를 세팅해주는 함수를 가볍게(?) 만들어 놨다.

// 받아온 장난감 리스트 
const [toyList, setToyList] = useState([]);
const loading = useRef<boolean>(false);

// 기본 페이지 초기값 설정
  const [page, setPage] = useState({
    current: 1, // 현재 페이지
    total: 0,   // 전체 페이지
  });

// 페이지 값을 인자로 받아 페이지 정보를 변경 
  function setPageInfo (currentPage: number) {
      setPage({
        ...page,
        current: currentPage,
      });
  }

 

 

useEffect를 사용하여 페이지가 바뀔 때마다 필요한 만큼의 리스트를 받아올 수 있도록 해보자

loading.current 의 역할은 데이터를 받아오는 중에는 중복 호출이 안되게 해주는 작지만 중요한 역할이다!

// 페이지가 바뀌면 데이터 fetching 을 하자
  useEffect(() => {
    if (!loading.current) {
      const totalCount = getCount(); // 카운트 값을 부르고
      getList(totalCount);	     // 그값을 넣고 리스트를 부르자 
    }
  }, [page]);

 

getCount 로 전체 리스트 갯수를 리턴해주자

getList 에서는 전체 리스트 갯수와 더불어 현재 페이지# 을 매개변수로 받아 내부로직에 의해 필요한 리스트만큼만 호출한다

async function getCount() {
	// 리스트 전체 갯수를 받아옴
    const [count, countErr] = await getListCount(); // api 함수

	// 에러 처리
    if (countErr) {
      countErr.alert = {
        message: '정보를 가져오는 데 실패했습니다.',
        type: CONSTANTS.ERROR_TYPE.NETWORK,
      };
      return;
    }
    
    // 리스트 전체 갯수를 pageInfo에 업데이트 해주자
    setPage({
      ...page,	    // 나머지는 그대로고
      total: count, // 전체페이지 수만 변경
    });
    
    return count;
}

async function getList(count: number) {
    loading.current = true;
    setToyList([]); // 리스트 정합성을 위해 초기화
 	
    // 딱 특정 페이지에 필요한 범위의 배열만 받아온다. 
    const [resList, listErr] = await getToyList(count, page.current);

    if (listErr) {
      countErr.alert = {
        message: '정보를 가져오는 데 실패했습니다.',
        type: CONSTANTS.ERROR_TYPE.NETWORK,
      };
      dispatch(addError(listErr));

      loading.current = false;
      return;
    }

    setToyList(resList);
    loading.current = false;
}

 

 

장난감 리스트를 뿌려주고,

더보기를 누를 때마다 계속 다음 리스트를 가져와 뿌려주고,

다 보면 접기를 눌러 처음 리스트만 남겨주자 :)

// 장난감 리스트를 보여주고
{toyList.map((toy, index) => (
  <div className="toy-item" key={toy.id}>
    <ToyItem toy={toy} />
  </div>
))}

// 총 페이지 수가 5p 이상이고, 현재 페이지가 총 페이지보다 적을 때,
{page?.total > 5 && page.total >= page.current && (
  <div className="more" onClick={() => setPageInfo(page.current + 1)}>
     더보기
   </div>
)}

// 총 페이지 수가 5p 이상이고, 현재 페이지가 총 페이지보다 같거나 커지게 될 때,
{page?.total > 5 && page.total <= page.current && (
   <div className="fold" onClick={() => setPageInfo(0)}>
    접기
   </div>
)}

 

 

 

 

엄청 예전에 정리해놓은 코드였는데, 나름 좀더 다듬어 리팩토링해보았다.
작년의 내가 이랬구나를 알 수 있는 시간였고, 내년의 나또한 기대가 되는 시간이였다 :)

 

 

 

 

 

 

 

 

반응형

댓글