React 페이지네이션 구현

김진원·2023년 12월 4일
0

React

목록 보기
3/4
post-thumbnail

페이지네이션?

페이지네이션이란 많은 데이터의 리스트들을 여러 페이지로 나눠, 한 화면에서 과도한 스크롤 및 이동등을 최소화 시킬 수 있는 기법입니다.

직접 구현? 라이브러리?

페이지네이션 관련하여 React Pagination component 혹은 Material UI 등과 같은 라이브러리가 있습니다.
하지만 오늘은 직접 구현함으로써 원리에 대해 고민해보고 실행해보는 시간을 갖도록 할 것입니다.

Newsapi 사용

먼저 리액트 마운트 시 페이지네이션 리스트에 필요한 데이터를 불러옵니다.
데이터는 axios를 통해 데이터를 수신 해줍니다.

    // newsData
    let [newsData, setNewsData] = useState(null);

    //  news api 데이터 받기
    const newsGet = async () => {
        try {
            const res = await axios.get(`${newsUrl}`);
            setNewsData(res.data.articles);
            setPageNum(res.data.articles.length / maxPage);
        } catch (err) {
            console.log("error");
        }
    };

    // Mount 시 데이터 수신
    useEffect(() => {
        newsGet();
    }, []);

console등을 통해 데이터가 정상적으로 불러와지는걸 확인해줍니다.

페이지네이션 구현 고민

페이지네이션을 직접 구현해보는 것은 처음이기에 작동 원리에 대해서 고민을 많이 했습니다.
구현 목표는 다음과 같았습니다.
1. 페이지당 보여줄 컨텐츠의 최대 개수
2. 데이터 수에 따른 페이지네이션 버튼 생성
3. 페이지네이션 버튼 클릭 시 해당 데이터 출력

페이지네이션 구현

먼저 1,3번의 경우 최대 보여줄 컨텐츠의 개수를 5로 정의 하는것과 현재 보고있는 index를 변수로 정의하여, slice 함수의 값을 곱해주고 빼주는것으로 구현 했습니다. getData라는 함수를 지정하여 pagiantion 버튼 클릭 시 현재 index의 값을 업데이트 해주었습니다.

pageList.js

    <>
            <PageList>
                {newsData != null ? (
                    <>
                        {newsData
                            .slice(newsSlice[0], newsSlice[1])
                            .map((item, idx) => {
                                return (
                                    <NewsArticles
                                        key={item.title}
                                        title={item.title}
                                        num={idx}></NewsArticles>
                                );
                            })}
                    </>
                ) : null}
            </PageList>
            <PaginationWrap
                pagenum={pageNum}
                getData={getData}></PaginationWrap>
        </>

paginationBtn.js

const PaginationBtn = (props) => {
    // 버튼 클릭 시 pageList까지 클릭한 index 데이터 전달
    const btnNum = (e) => {
        e.preventDefault();
        props.getData(e.target.textContent);
    };

    return (
        <PageBtn onClick={btnNum} role="button">
            {props.num}
        </PageBtn>
    );
};

함수를 자식 컴포넌트의 내려줌으로써 현재 index를 업데이트하고, 부모 페이지는 업데이트 된 index를 기반으로 slice 함수를 통해 데이터를 화면에 출력합니다.

2번 페이지네이션 버튼 생성 같은 경우는 전체 데이터의 length / 페이지 당 컨텐츠 최대 개수를 변수로 지정하여 map으로 화면에 출력해주었습니다.
21같은 5의 나머지가 0이 아닌 경우여도, 페이지네이션의 버튼은 6이 되어야하니 Math.ceil 함수를 통해 소수점 단위는 올림 해주었습니다.

paginationWrap.js

 setPageNum(res.data.articles.length / maxPage);
 
 const PaginationWrap = (props) => {
    return (
        <div>
            {[...Array(parseInt(Math.ceil(props.pagenum)))].map((item, idx) => {
                return (
                    <PaginationBtn
                        key={idx}
                        num={idx + 1}
                        getData={props.getData}></PaginationBtn>
                );
            })}
        </div>
    );
};

news의 경우 간단한 타이틀만 화면에 출력해줌으로써 원하던 목표는 모두 달성했습니다.

페이지네이션을 구현하면서...

일상속에서도 자주 접하는 페이지네이션을 간단하지만, 직접 구현함으로써 원리에 대해 고민해보는 좋은 시간이었습니다.
slice등과 같은 함수를 통해 구현하니 js에 좀 더 집중하고 문제에 있어 어떤 식으로 접근하고 어떤식으로 해결할지 등에 대해 좀 더 빠르고 정확한 판단을 내려야겠습니다.

추후에 React pagination component와 같은 라이브러리도 접해보고,
pagination 버튼도 최대 출력 개수와 prev, next 기능도 추가 해보도록 하겠습니다.

전체코드는 아래를 참고 해주세요.
리액트 페이지네이션 github

profile
사용자의 관점에 대해 욕심이 많은 개발자

0개의 댓글