본문 바로가기
CodeIt_Sprint/React로 데이터 다루기

(6)React로 데이터 다루기_6_웹페이지를 열 때, 있는 데이터를 전부 불러오는 것이 아닌, 부분 데이터만 fetch하고, 필요할때만, 데이터를 fetch하기 => 페이지네이션(작성중..시발 존나어렵다)

by 코잼민 2024. 12. 31.

● 이론1_ 페이지네이션(Pagenation) :

○ 일반적 페이지네이션 예시 상황 :

- 어떤 뉴스 웹페이지를 열 때, 모든 뉴스 데이터를 불러오는 것이 아닌, 일부분만 출력해주고,

- '더 보기' 버튼을 누를 때, || 커서를 내릴 때, => 그 동작 후에 몇개의 데이터를 불러온다.

○ 페이지 네이션 종류 : 2가지

- 종류1_ 오프셋 기반 페이지네이션 : 데이터 개수를 기반으로 한 페이지네이션

예) Request

Get https://example.com/posts?offset=20&limit=10

해석 :

  • offset = 20 //현재 20개의 데이터 불러온 상태인데,
  • limit=10 //동작 후에는 10개를 더 보내주는 예약어

- 서버로부터 받은 Response 내용

{
	"padding" : {
    	"count" : 30,
        "hasNext" : false
    },
    "posts" : [....]
}

- 오프셋 기반의 페이지 네이션 문제점

=> 데이터 구성이 자주 바뀌는 상황에서 사용할 때, 일부 데이터가 중복이나 생략이 될 수 있다. //블로그

처음 offset 상황
새로운 글이 추가된 후의 다음 offset 상황

 

- 종류2_ 커서 기반 페이지네이션 : 데이터를 가리키는 값 , 책갈피를 기반으로 한 페이지네이션

예) Request

Get https://example.com/posts?limit=10

해석 :

  • limit=10 //동작 후에는 10개를 더 보내주는 예약어

- 서버로부터 받은 Response 내용

{
	"padding" : {
    	"count" : 30,
        //"hasNext" : false
        "nextCursor" : "WerZxc"//다음 커서값을 넘겨준다.
    },
    "posts" : [....]
}

- 서버로부터 받은 Response 내용을 기반으로 다시 Request 내용 :

Get https://example.com/posts?cursor=WerZxc&limit=10

데이터 구성이 변하더라도, 가리키는 값은 변하지 않으므로, 중복, 생략 문제 발생 X

단점 : 오프셋기반 페이지내이션보다 만들기 까다롭다.

 

● 이론2_ 페이지네이션(Pagenation) 실습 

○ 구현할 상황 :

- 처음에는 6개 데이터만 불러오고, '더보기' 버튼을 누를 시, 6개씩 더 데이터를 불러와 렌더링 하기

- 모든 데이터를 불러왔을 시, => '더 보기' 버튼을 비활성화 하기

○ 코드 순서 :

▶순서1_ 데이터 불러오는 Get 리퀘스트 메소드에 Argument와 , query 변수 에 limit, offset 반영하기 :

//Argument를 객체 형태, + offset =0 , limit = 6 으로 적용
//해석 : 초기에는 6개만 데이터 불러오도록 한다.
export async function getReviews({order='createdAt' , offset=0 , limit=6})
{
	cosnt query = `order=${order}&offset=${offset}&limit=${limit}`;
    //query 문자열에 limit , offset 반영
    const response = await fetch(`https://learn.codeit.kr/api/film-reviews?${query}`);
    
    const body = await response.json();
    
    return body;
}

▶순서2_ App컴포넌트로 돌아가서, 데이터 인출 핸들러 메소드 + useEffect 메소드 수정 :

- 데이터 인출 핸들러 //handleLoad()

//데이터 인출 핸들러 , Argument를 orderQuery =>limit, offset 반영의 변수 'options'로 수정
const handleLoad = async (options)=>{
	const {reviews} = await getReviews(options);
    
    setItems(reviews);
}

- useEffect(콜백 , [검사용 내용물]);

const LIMIT = 6;//6개씩 불러오는 건 동작 중에 변화 없을 것이므로, const 상수로 저장

//useEffect의 콜백 함수 내의 handLoad()메소드 매개인자에 offset=0,limit=6 을 반영한 객체를 매개인자로 대입
useEffect(()=>{
	handleLoad({order,offset : 0 , limit : LIMIT});
},[order]);

▶★순서3_ App컴포넌트에 '더보기'버튼 추가, 핸들러 적용 과정1 :

=> 동작에 따라 offset 값이 변화되므로, => useState 초기화

const [offset , setOffset] = useState(0);

 

=> handLoad에서 fetch된 Promise 객체의

- 데이터 인출 핸들러 //handleLoad() 추가 적용 :

const handleLoad = async (options)=>{
	const {reviews} = await getReviews(options);
	
    //받은 reviews 객체의 offset에 따른 items배열 업데이트
    if(reviews.offset==0)
    {
		setItems(reviews);
    }
    else{
		setItems([...items],...reviews]);
        //배열형태의 데이터를 안전하게 업데이트 하는 방법 => spread문법
    }
    
    //offset도 수정
    setOffset(options.offset + reviews.length);
    //기존 데이터 개수 + 더보기 동작으로 새로 추가된 데이터의 개수
}

 

▶순서4_ 데이터를 모두 불렀을 시, 더보기 버튼 비활성화 기능 적용 => hasNext의 값으로 구현

- 동작에 따라 hasNext 값이 변화되므로, => useState 초기화

const [offset , setOffset] = useState(0);
const [hasNext, setHasNext] = useState(false);
//초기값은 false

※참고로, hasNext모든 데이터가 불러올 시 ,false가 된다.

- '더보기' 버튼을 누를 시, 반환된 reviews데이터의 hasNext 값을 hasNext에 업데이트

  const handleLoad = async (options) => {
    const { reviews } = await getReviews(options);
    if (options.offset === 0) {
      setItems(reviews);
    } else {
      setItems([...items, ...reviews]);
    }
    setOffset(options.offset + options.limit);
    setHasNext(reviews.hasNext);//업데이트
  };

 

- 버튼 태그의 disabled 속성에 hasNext 가 false가될 시, 발현되도록 코드 작성 :

      <button disabled={!hasNext} onClick={handleLoadMore}>
        더 보기
      </button>