본문 바로가기
⚛️ React

query parameter를 사용하여 pagination 구현하기

by 슬용이 2022. 6. 5.

pagination

한 번에 많은 데이터를 렌더하게 되면 성능이 떨어지면서 사용자 편의성이 감소하기 때문에 데이터를 나눠 내려받게 되는데 가장 많이 쓰이는 페이지를 나누는 방식을 뜻하는 것이 바로 pagination 기능이다.

 

query parameter

pagination을 위해 사용하는 것이 쿼리 파라미터(쿼리 스트링)이며, 말 그대로 엔드포인드 뒤에 ?(쿼리)를 보내는 요처을 한다. limit과 offset을 설정할 수 있으며, offset은 데이터가 시작하는 위치(index)를 뜻하고, limit은 내려받을 데이터의 수를 뜻한다.

 


 

우선 버튼을 클릭했을 때 정상적으로 동작하는지 확인하기 위해 console.log를 적어줘야 한다.

 

const getBtnIndex = () => {
    console.log("hello");
  };

 

Button 컴포넌트에 생성한 함수 전달하고 클릭하면 끝

 

<Buttons getBtnIndex={getBtnIndex} />
export default function Buttons({ getBtnIndex }) {
  return (
    <div className="pageBtn">
      <button onClick={getBtnIndex}>1</button>
      <button>2</button>
      <button>3</button>
      <button>4</button>
      <button>5</button>
    </div>
  );
}

1번 버튼을 눌렀을 때 정상적으로 hello가 console에 출력되는 것을 볼 수 있다.

외부 함수가 컴포넌트 내에서 정상적으로 동작하는 것은 확인하였다.

그러면, 우리가 하고자 했던 것을 할려면 button의 값을 알아야 한다.

 

<button onClick={(e) => {console.log(e.target);}}>1</button>

 

button에 event를 인자로 받아서 받고 있는 target이 정상적으로 나오는지 확인해보자.

 

button안의 숫자값만 갖고 싶다면 .innerHTML을 추가하여 아래와 같이 수정해주자.

 

<button onClick={(e) => {console.log(e.target.innerHTML);}}>1</button>

하지만 우리는 내려받은 data의 index 값을 좀 더 편하게 보기 위해서 시작값인 1번 0으로 바꿔 주는 것이 좋다.

-1을 하여 각각의 버튼을 눌렀을 때 1,2,3,4,5가 아닌 0,1,2,3,4,5로 변경해주자.

 

그리고 다시 함수에 해당 값을 전달해주기 위해 console.log가 아닌 getBtnIndex에 인자를 넣어주자.

 

<button onClick={(e) => {getBtnIndex(e.target.innerHTML);}}>1</button>

 

getBtnIndex함수에는 변수를 전달 받을 수 있게 값을 적어주자.

 

const getBtnIndex = (btnIndex) => {
    console.log(btnIndex);
  };

다시 함수에서 정상적으로 값을 전달받았는지 확인을 해 본 다음,

limt값과 offset 값을 지정해주자.

 

const getBtnIndex = (btnIndex) => {
    const limit = 4;
    const offset = btnIndex * limit;
    console.log(offset);
  };

 

limit를 4라고 했을 때 전달받는 offset 값은 각각의 button 숫자에서 limit 갯수가 곱해진 값이다.

  • 1번 페이지에서 0번부터 4개 노출 ( 0~3 (0, 1, 2, 3))
  • 2번 페이지에서는 4번부터… (4~7 (4, 5, 6, 7))
  • 3번 페이지에서는 8번부터… (8~11 (8, 9, 10, 11))

console을 확인해보면 각각의 시작 index 값이 잘 찍히는 것을 볼 수 있다.

그럼 이제 우리가 할 일은 query string을 navigation으로 전달하여 버튼이 눌렸을 때

각각 offset값에 맞는 data를 불러올 수 있게 해줘야 한다.

 

const getBtnIndex = (btnIndex) => {
    const limit = 4;
    const offset = btnIndex * limit;
    const queryString = `?offset=${offset}&limit=${limit}`;
    console.log(queryString);
  };

 

queryString을 지정하여 url에 값이 전달될 수 있도록 offset과 limit를 백틱을 이용하여 작성해주도록 하자.

 

버튼을 눌렀을 때 console에 offset값이 바껴 나오는걸 잘 볼 수 있다.

이제 url을 바꿔줘야하니 useNavigate 훅을 추가하고,

 

import { useNavigate } from "react-router-dom";

 

navigate 함수를 지정해주자.

 

const navigate = useNavigate();
const getBtnIndex = (btnIndex) => {
    const limit = 4;
    const offset = btnIndex * limit;
    const queryString = `?offset=${offset}&limit=${limit}`;
    navigate(`${queryString}`);
  };

 

navigate 함수에 동적으로 변하는 queryString을 인자로 넣어주면 끝!

 

navigate(`/${queryString}`);

 

navigate 인자를 지정할 때 앞에 ‘/’ 를 적게 되면 로컬호스트의 뒷 부분을 아예 삭제해버리니 조심하도록 하자

 

localhost:3000/pagination?offset=0&limit=4

 

으로 나와야하는 것이

 

localhost:3000/?offset=0&limit=4

 

이렇게 나오게 된다.

그러니 꼭 아래와 같이 쓰거나,

 

navigate(`${queryString}`);

 

‘/’를 쓰려면 엔드포인드까지 모두 맞춰서 적어주도록 하자!

 

 

그럼 이제 버튼을 누를 때 url이 바뀌는 것까지는 확인을 했다

url에 맞는 data를 요청해서 내려 받기 위해서 useLocation을 이용하도록 하자

 

import { useNavigate, useLocation } from "react-router-dom";
const location = useLocation();
  console.log(location);

 

location 함수를 지정해주고, 어떤 값을 받아오는지 확인해보자.

 

우리가 써야할 부분은 search 부분이다.

그럼 location.search 값을 fetch 함수 안의 url에 전달해주자.

 

useEffect(() => {
    fetch(`http://localhost:8000/users${location.search}`)
      .then((res) => res.json())
      .then((res) => setUsers(res.users));
  }, []);

 

그럼 지정해놓은 offset 값인 4만큼 내려오는 것을 확인할 수 있다!

하지만 버튼을 누른 후 새로고침을 해야 값이 바뀌는데 그 이유는 url이 바뀌어도 렌더를 새로하지 않기 때문이다.

우리는 useEffect의 의존성 배열 특징을 여기에서 사용할 수 있다.

 

useEffect(() => {
    fetch(`http://localhost:8000/users${location.search}`)
      .then((res) => res.json())
      .then((res) => setUsers(res.users));
  }, [location.search]);

 

의존성 배열은 값이 바뀔 때 마다 렌더를 새로 해주기 때문에 location.search 값인 url이 바뀔 때 마다 렌더를 새로 해주게 된다.

그럼 원래 우리가 의도한 대로 정상작동! 하는 것을 볼 수 있다.

 

 


 

댓글