리액트 : 게시글 '+더보기 버튼' 구현 : 시도(1)

728x90
반응형

[최종 사용: useInfiniteQuery]

 

타입스크립트 + useInfiniteQuery : 더보기 기능 구현

https://tanstack.com/query/latest/docs/react/guides/query-functions#queryfunctioncontext Query Functions | TanStack Query Docs A query function can be literally any function that returns a promise. The promise that is returned should either resolve the dat

zerotonine2da.tistory.com


 

[사용]

* DB : 파이어베이스

* React Query

* TypeScript

 

[로직]:더보기 기능 (관리자용)
  // 1. itemPerRow : 기본 개수 (4 개)
  // 2. startIndex : 배열 slice에서 사용되는 시작 index (값: 0)
  // 3. cnt : 더보기 클릭시 개수 (cnt = 1 : 기본 4개 보여주기 위해서 1로 시작)
  // 3. endIndex : startIndex + itemPerRow * cnt
  // 4. DisplayItem : 배열(관리자/selectedCategory).slice(startIndex,endIndex)
  // 5. 더보기 클릭시 cnt ++

 

[구현]

[usePaginatedItem.ts]-- 훅

import { useEffect, useState } from 'react';

export default function usePaginatedItem(data: PostType[], itemPerRow: number) {
  const [cnt, setCnt] = useState<number>(1);
  const [displayData, setDisplayData] = useState<PostType[]>([]);

  useEffect(() => {
    const endIndex = itemPerRow * cnt;
    setDisplayData(data.slice(0, endIndex));
  }, [data, cnt]);

  useEffect(() => {
    // data가 변경될 때 cnt를 1로 초기화
    setCnt(1);
  }, [data]);

  const showMore = () => setCnt((prev) => prev + 1);

  return { displayData, showMore };
}

 

[ViewAllBody.tsx]

  //커스텀 훅 : 더보기 기능 (관리자용)
  const ITEM_PER_ROW = 4;
  const { displayData: displayAdminData, showMore: showMoreAdmin } = usePaginatedItem(
    adminQuery.data || [],
    ITEM_PER_ROW
  );

  //커스텀 훅 : 더보기 기능 (사용자용)
  const { displayData: displayUserData, showMore: showMoreUser } = usePaginatedItem(
     selectCategory || [], 
     ITEM_PER_ROW
);
 
return (
        <St.ContentsWrapper>
          <St.Contents>
            {displayAdminData?.map((item) => (
              <St.Content key={item.id}>
                <p>{item.title}</p>
                <p>{item.content}</p>
                <p>{item.category}</p>
              </St.Content>
            ))}
          </St.Contents>
        </St.ContentsWrapper>
        <button onClick={showMoreAdmin}>더보기...</button>

 


1. 코드 구현

[ViewAllBody.tsx]

  const itemPerRow = 4;
  const startIndex = 0;
  let endIndex = 0;
  const [cnt, setCnt] = useState(1);
  const [DisplayAdminItem, setDisplayAdminItem] = useState<PostType[]>([]);

  useEffect(() => {
    if (adminQuery.data) {
      endIndex = startIndex + itemPerRow * cnt;
      setDisplayAdminItem(adminQuery.data.slice(startIndex, endIndex));
    }
  }, [adminQuery.data, cnt]);

  //더보기 버튼
  const handleShowMoreClick = () => {
    setCnt((prev) => prev + 1);
  };

▶ 관리자용 & 사용자 카테고리별로 사용해야하기에 코드 중복을 줄이기 위해 커스텀 훅으로 변경 필요해보임.

 

"커스텀 훅으로 개선"

[usePaginatedItem.ts]

import { useEffect, useState } from 'react';

export default function usePaginatedItem(data: PostType[], itemPerRow: number) {
  const [cnt, setCnt] = useState<number>(1);
  const [displayData, setDisplayData] = useState<PostType[]>([]);

  useEffect(() => {
    const endIndex = itemPerRow * cnt;
    setDisplayData(data.slice(0, endIndex));
  }, [data, cnt]);

  const showMore = () => setCnt((prev) => prev + 1);

  return { displayData, showMore };
}

데이터와 한줄에 표시될 숫자 매개변수로 받기

▶ cnt 초기값은 1

▶ 데이터 : 관리자 게시물 / 사용자 게시물 ( 4가지 카테고리 )

▶ useEffect()에서 선택된 데이터를 slice로 보여주는 개수 정하기 (데이터&cnt 값을 dependency array로 설정)

 

▶ showMore은 더보기 클릭시 cnt 증가

 

[문제]

[ViewAllBody.tsx]

const { displayData: displayUserData, showMore: showMoreUser } = usePaginatedItem(selectCategory || [], ITEM_PER_ROW);
  //버튼 클릭시 해당 카테고리 선택
  const handleButtonsClick = (category: PostType[] | undefined) => {
    if (category) {
      setSelectCategory(category);
    } else {
      setSelectCategory([]);
    }
  };
        <St.ButtonWrapper>
          <St.Button onClick={() => handleButtonsClick(knowHowQuery.data)}>친환경 노하우</St.Button>
          <St.Button onClick={() => handleButtonsClick(recommendQuery.data)}>제품 추천</St.Button>
          <St.Button onClick={() => handleButtonsClick(shareQuery.data)}>제품 나눔</St.Button>
          <St.Button onClick={() => handleButtonsClick(habitQuery.data)}>습관 인증</St.Button>
        </St.ButtonWrapper>

 

▶ 버튼 클릭할때마다 동일 함수를 사용하여 매개변수에 받는 카테고리로 지정하여 데이터를 전달하였는데

같은 커스텀 훅을 사용하니, 같이 동작함 

(예, 친환경노하우 카테고리에서 "더보기" 클릭하면 제품추천은 이미 데이터가 "더보기" 기능이 적용되어있음)

 

[개선]

[usePaginatedItem.ts]

  useEffect(() => {
    // data가 변경될 때 cnt를 1로 초기화
    setCnt(1);
  }, [data]);

▶ 간편하게 수정하기 위해서 커스텀 훅에서 data가 변경될때 cnt 값을 1로 초기화

=> 더보기 : 선택된 데이터를 slice로 보여주는 개수 정하기가 초기화 되어 초기 4개만 출력됨

 

 

끝.

반응형