리스트를 보여주는 화면에서, arrow를 앞 뒤로 왔다갔다하면 여러 개의 페이지가 보여지는 것을 말한다. 이를 한번 구현해보자.
일단 useState
를 하나 만들어야 하는데 다음과 같이 만들어 보자. ShowPostList.jsx
에 다음 코드를 입력한다.
...
const ShowPostList = ({apiUrl}) => {
const [loading, setLoading] = useState(true);
const [isPost, setIsPost] = useState(false);
const [postList, setPostList] = useState([]);
const [page, setPage] = useState
...
pagination을 랜더링하기 위하여, map을 통하여 이용할 것이다. 전체 페이지의 개수가 몇개인지 확인을 해 보자.
우리가 받아온 데이터의 count를 확인해보면
92임을 알 수 있다. 전체 글의 개수가 총 92개인데, 우리가 10개만 보여주는 것만이 10개이기 때문에 이정도밖에 안보이는 것이다.
우리는 이 페이지를 나누기 위하여 페이지 데이터를 가져와, 계산을 해야 한다. 92라는 수를 올림을 하여 10으로 나누어 보자. (10페이지가 보여야 하기 때문)
useEffect(() => {
axios.get(`${apiUrl}list/?page=1&page_size=10`).then(response => {
console.log(response.data);
Math.ceil(response.data.count / 10);
setPostList(response.data.results);
setLoading(false);
})
},[]);
여기서의 Math.ceil(response.data.count / 10);
가 전체 페이지의 개수를 담고 있는 공식이 될 것이다.
전체 페이지를 담고 있는 state가 필요해보이니 추가해보자.
const [pages, setPages] = useState([]);
저기 [] 빈칸에 페이지의 수가 다음과 같이 입력되겠지?
[1,2,3,4,..]
원래는 이렇게 되어야 한다. 이 값을 업데이트 시키기 위해 변수를 하나 만들고 다음과 같이 설정해보자.
useEffect(() => {
axios.get(`${apiUrl}list/?page=1&page_size=10`).then(response => {
console.log(response.data);
const lastPage = Math.ceil(response.data.count / 10);
const tempPages = [];
for(let i = 1 ; i <= lastPage ; i++){
tempPages.push(i);
}
setPages(tempPages);
setPostList(response.data.results);
setLoading(false);
})
},[]);
위의 for문을 돌리면서 우리가 가져야 하는 최대 페이지를 계산하고, 그 페이지의 값을 state 업데이트 시키는 방향으로 설정을 완료하였다.
자. 이제 우리가 만든 pages
라는 state를 진짜로 번호 넣는것에 map 형식으로 만들어 넣으면 되겠죠!
</PagenumberDiv>
{pages.map(pageNum => (
<PagenumberDiv key = {pageNum} > {pageNum} </PagenumberDiv>
))}
<PagenumberDiv>
짜잔~ map을 활용하여 진짜 수를 넣어요.
일단 번호가 뜨는 것은 성공했다!
이제, 해당 페이지 번호를 누르면, 진짜로 그 페이지에 맞는 데이터가 바뀌어 등장하는 방법에 대해서 알아보도록 하자.
useEffect(() => {
axios.get(`${apiUrl}list/?page=1&page_size=10`).then(response => {
console.log(response.data);
const lastPage = Math.ceil(response.data.count / 10);
const tempPages = [];
for(let i = 1 ; i <= lastPage ; i++){
tempPages.push(i);
}
setPages(tempPages);
setPostList(response.data.results);
setLoading(false);
})
},[]);
위 코드의 useEffect
를 현재 처음 페이지를 불러올 때만 한번 랜더링 되는 것이 아니라, 페이지가 바뀔 때마다 새롭게 시작할 수 있도록 바꾸어 주어야 하는 것이다.
useEffect(() => {
axios.get(`${apiUrl}list/?page=${page}&page_size=10`).then(response => {
console.log(response.data);
const lastPage = Math.ceil(response.data.count / 10);
const tempPages = [];
for(let i = 1 ; i <= lastPage ; i++){
tempPages.push(i);
}
setPages(tempPages);
setPostList(response.data.results);
setLoading(false);
})
},[page]);
그래서 이렇게, page
가 업데이트 될 때마다 useEffect
가 실행할 수 있도록 바꾸어 주었다.
그리고
{pages.map(pageNum => (
<PagenumberDiv key = {pageNum} onClick = { () => setPage(pageNum)}> {pageNum} </PagenumberDiv>))}
해당 페이지를 클릭할 때마다 페이지를 바꾸는 기능을 넣어준다. 그럼 페이지를 클릭할 때마다 다른 내용이 뜨는 것을 확인할 수 있다.
자, 이제 앞으로 가기, 뒤로 가기 버튼을 구현해보자. <-, ->가 기능도 없이 있으면 안되니까!
<PagingSection>
<PagenumberDiv onClick = {() => setPage(page-1)}>
<FontAwesomeIcon icon = {faArrowLeft}/>
</PagenumberDiv>
{pages.map(pageNum => (
<PagenumberDiv key = {pageNum}
onClick = { () => setPage(pageNum)}> {pageNum} </PagenumberDiv>
))}
<PagenumberDiv onClick = {() => setPage(page+1)}>
<FontAwesomeIcon icon ={faArrowRight}/>
</PagenumberDiv>
</PagingSection>
+1, -1을 통하여 작동하도록 해 주었다.
그런데 마지막 페이지와 첫 페이지도 +1, -1 페이지가 될 수 있으니까 이를 방지하여 보자.
<PagenumberDiv onClick = {() => {
if (page > 1) {() => setPage(page-1)}}}>
<FontAwesomeIcon icon = {faArrowLeft}/></PagenumberDiv>
{pages.map(pageNum => (
<PagenumberDiv key = {pageNum} onClick = { () => setPage(pageNum)}> {pageNum} </PagenumberDiv>))}
<PagenumberDiv onClick = {() => {
if(pages.length > page) {setPage(page+1)}}}>
<FontAwesomeIcon icon ={faArrowRight}/></PagenumberDiv>
이렇게 코드를 작성하여 작을때만, 클때만 페이지가 넘어가도록 한다.
하지만 UX관점에서 보면 1페이지와 마지막 페이지에, 화살표가 사라지는 것도 좋을 것 같다 :)