React-admin으로 관리자 페이지 만들기 : 페이지네이션 에러

김지욱·2020년 11월 21일
0

React-admin

목록 보기
2/2
post-thumbnail

React-admin 페이지네이션 적용 에러

💬 문제

react-admin의 Data Previder부분을 보면 아래와 같은 방식으로 데이터를 가져올 때 페이지 네이션 기능이 적용이 된다고 생각하고 코드를 작성했었다.

//dataProvider

getList: (resource, params) => {
        const { page, perPage } = params.pagination;
        const { field, order } = params.sort;
        const query = {
            sort: JSON.stringify([field, order]),
            range: JSON.stringify([(page - 1) * perPage, page * perPage - 1]),
            filter: JSON.stringify(params.filter),
        };
        const url = `${apiUrl}/${resource}?${stringify(query)}`;

 **       return httpClient(url).then(({ headers, json }) => ({
            data: json,
            total: parseInt(headers.get('content-range').split('/').pop(), 10),
        }));
    },

맨 아래줄의 total 부분에서 나는 이전 포스팅 에서 X-Total-Count 로 데이터 길이를 가저오고 있었기 때문에 이 부분만 아래와 같이 수정을 해주었다.

total: parseInt(headers.get("X-Total-Count").split("/").pop(), 10),

이렇게 하면 전체 리스트를 가저오는 페이지에서 페이지 네이션 기능이 잘 적용이 된 거 처럼 보인다.

하지만 NEXT를 누르거나 페이지 번호를 이동해도 화면에 아무런 변화가 일어나지 않는 문제를 발견했다.

🤔 원인

getList 로 전체 리스트를 받아올 때 어떤 식으로 서버에 요청이 가고 있는지 확인을 해봤다.

/userlist?filter=%7B%7D&range=%5B0%2C9%5D&sort=%5B%22id%22%2C%22ASC%22%5D

req.url 을 확인해보면 위에처럼 요청을 보내고 있는 걸 확인할 수 있었다.

url 을 이용하면 될 거 같다는 생각이 들어서 DataProvider에서 url을 정의하는 부분을 내가 필요한 내용들로 알기쉽게 수정해 보기로 했다.

🔗참고링크

//dataProvider

getList: (resource, params) => {
    const { page, perPage } = params.pagination;
    const { field, order } = params.sort;
    const { q } = params.filter;
    console.log(":::::page::::", page);
    console.log(":::::q:::::", q);
    console.log("::::perPage:::::", perPage);

    // Pagination and sort
    const query = `limit=${perPage}&page=${page}&orderBy=${field}&orderDir=${order}&search=${q}`;
    // Filter?
    console.log("::::query:::::", query);

    const url = `${apiUrl}/${resource}?${query}`;
    console.log(":::::url::::", url);
    return httpClient(url).then(({ headers, json }) => ({
      data: json,
      total: parseInt(headers.get("X-Total-Count").split("/").pop(), 10),
    }));
  },

getList 를 이렇게 수정하고 다시 서버 쪽 요청을 확인해 봤다.

/admin/beerlist?limit=10&page=1&orderBy=id&orderDir=ASC&search=undefined

이 요청에 담긴 req.url 에서 limitpage 를 활용하면 페이지 네이션을 사요할 수 있게다는 생각이 들었다.

💡 해결

/admin/beerlist?limit=10&page=1&orderBy=id&orderDir=ASC&search=undefined
/admin/beerlist?limit=10&page=2&orderBy=id&orderDir=ASC&search=undefined
/admin/beerlist?limit=10&page=3&orderBy=id&orderDir=ASC&search=undefined

페이지를 이동할 때마다 url 쿼리에서 page부분이 변하는걸 확인할 수 있었다.

  • 여기서 limitpage 를 추출한다.
  • 1페이지에서 데이터 10개를 보내고 2페이지에서 처음 10개를 제외한 10개를 보내준다.

limit=10 page=2 일때 id가 11 ~ 20까지의 리스트를 보내준다. 이걸 식으로 작성해보면

  • ( limit x page ) - limit ~~ ( limit x page ) 안의 범위를 구한다.

limitpage 를 추출할 방법으로 처음에는 slice나 split를 생각했지만 limit 의 자리수가 변하거나 하는 등의 변수가 발생할 수 있기 때문에 정규식을 이용해 보기 로했다.

const url = '/userlist?limit=10&page=1&orderBy=id&orderDir=ASC';
const getLimit = /limit=(\d+(\d)*)/;
const getPage = /page=(\d+(\d)*)/;

const limit = url.match(getLimit);
const page = url.match(getPage);

위와 같은 방법으로 limit과 page 다음의 숫자를 가져올 수 있었다. 하나씩 뜯어보면,

\d : 숫자 하나와 매칭

limit=10 에서 limit 뒤의 1 을 가져온다.

(\d)* : 다음의 숫자가 있을 수도 있고 없을 수도 있는 경우

limit=10 에서 1 다음에 숫자가 있기 때문에 0 도 가져와서 10 이된다.

위의 내용들을 모두 코드로 적용해보았다.

// server/admin

const { url } = req;
const limitArr = url.match(/limit=(\d+(\d)*)/);
const pageArr = url.match(/page=(\d+(\d)*)/);

if (limitArr && pageArr) {
  const limit = Number(limitArr[1]);
  const page = Number(pageArr[1]);
	// string 배열로 나오기 때문에

  const start = limit * page - limit + 1;
  const end = limit * page;

  const sendBeerList = await Beer.findAll({
        raw: true,
        where: {
          id: {
            [Sequelize.Op.between]: [start, end],
          },
        },
        order: [[target, sort]],
      });
}

//생략..

이렇게하면 url 쿼리 요청으로 limit과 page에 맞는 범위의 데이터를 보낼 수 있었고 페이지 네이션 기능도 제대로 잘 작동하는 걸 확인할 수 있었다.

BIBA! 바로가기

2개의 댓글

comment-user-thumbnail
2021년 6월 7일

와 사이트 잘만드셨네요!!

1개의 답글