본문 바로가기

TIL

더보기 기능 구현하기

스터디 멤버들의 회고록 데이터여서 양이 그렇게 많지 않아 데이터 전체를 불러와 클라이언트에서 더보기 처리를 하였다.

만약 서버에서 많은 데이터를 불러오는 경우라면 API 호출 로직을 수정해야 할 것이다.

 

 

구현 기능

- 초기에 4개의 메모만 표시되고, 더보기 버튼을 클릭할 때마다 4개씩 추가로 메모가 표시됨

- 더 이상 표시할 메모가 없으면 더보기 버튼이 사라짐

 

 

구현 과정

1. useState 훅을 사용해 초기값이 4인 showItems 상태를 관리

const [showItems, setShowItem] = useState(4);

 

2. handleLoadMore 함수를 추가해 더보기 버튼 클릭 시 showItems + 4씩 증가

const handleLoadMore = () => {
    setShowItem((prev) => prev + 4);
  };

 

3. displayedMemos : data 배열에서 showItems 개수만큼 잘라낸 배열

const displayedMemos = data.slice(0, showItems);

 

4. hasMoreMemos 변수를 사용해 더 표시할 메모가 있는지 확인

const hasMoreMemos = showItems < data.length;

 

5. hasMoreMemos가 true일 때만 더보기 버튼 렌더링

{hasMoreMemos && (
        <button
          onClick={handleLoadMore}
          className="caption mt-5 flex items-center justify-center text-secondary-300"
        >
          <span>더보기</span>
          <Image
            src={"/icons/ChevronDownGray.svg"}
            alt="down"
            width={20}
            height={20}
          />
        </button>
      )}

 

 

전체 코드

"use client";

import Image from "next/image";
import { useStudyMemo } from "../[id]/hooks/usePersonalMemo";
import PersonalMemoItem from "./PersonalMemoItem";
import { useState } from "react";
import Loading from "@/components/common/Loading";

const PersonalMemos = ({ studyId }: { studyId: string }) => {
  const { data, isLoading, isError } = useStudyMemo(studyId);
  const [showItems, setShowItem] = useState(4);

  if (isLoading || !data) {
    return <Loading />;
  }

  if (isError) {
    return <div>회고록 목록을 불러오는데 실패했습니다.</div>;
  }

  // 더보기
  const handleLoadMore = () => {
    setShowItem((prev) => prev + 4);
  };

  // data 배열에서 showItems 개수만큼 잘라낸 배열
  const displayedMemos = data.slice(0, showItems);
  // 표시할 메모가 있는지 확인
  const hasMoreMemos = showItems < data.length;

  return (
    <div className="mb-[55px] flex w-full flex-col">
      <div className="mb-3 flex items-center p-1 pl-1">
        <Image src={"/icons/StudyMemo.svg"} alt="memo" width={16} height={16} />
        <h2 className="caption ml-1 text-white">스터디 회고록</h2>
      </div>
      {displayedMemos.map((item) => (
        <PersonalMemoItem key={item.memo_id} memoData={item} />
      ))}
      {hasMoreMemos && (
        <button
          onClick={handleLoadMore}
          className="caption mt-5 flex items-center justify-center text-secondary-300"
        >
          <span>더보기</span>
          <Image
            src={"/icons/ChevronDownGray.svg"}
            alt="down"
            width={20}
            height={20}
          />
        </button>
      )}
    </div>
  );
};

export default PersonalMemos;

 

 

 

🧐 느낀점

현재는 데이터 양이 적은 스터디 회고록이라 클라이언트 사이드에서 처리를 했지만, 대량의 데이터를 불러올 경우 적합하지 않을 것 같다.

그런 경우에는 페이지네이션이나 무한 스크롤을 서버 사이드에서 구현하는 것이 클라이언트의 메모리 관리나 초기 로딩 시간 측면에서 더 효율적일거라 생각된다. 작은 기능이지만, 프로젝트의 규모와 특성에 따라 구현 방식을 달리 해야할 듯하다.

'TIL' 카테고리의 다른 글

favicon & og 설정하기  (0) 2024.11.14
아키텍쳐, 다이어그램, 기능명세서 만들기  (0) 2024.11.13
css 우선순위 문제  (0) 2024.11.11
자체 UT 후 계획 및 버그수정  (1) 2024.11.08
shadcn/ui 캘린더 css 적용하기  (0) 2024.11.06