Pagination์ ๋ํ ์ฝ๋ ๊ตฌํ์ด ๋ง๋งํด์ codesandbox์์ ๊ด๋ จ๋ ์ฝ๋๋ฅผ ์์นญํด๋ณด์๋ค.
์ฌ๋ฌ๊ฐ์ง ์ํ ์ฝ๋๋ค ์ค์์, ์ ์ผ ๋ง์์ ๋๋ ์ฝ๋๋ฅผ ๋ณต์ฌํด์ ์ฌ์ฉํ๋๋ฐ,
์ฒ์ ๋ณด๋ ๋ฌธ๋ฒ์ด์๊ธฐ์ ์ด๋ค ๋ฌธ๋ฒ์ ์ฌ์ฉํ๊ฑด์ง ๊ทธ๋ฆฌ๊ณ ์ฝ๋๊ฐ ๊ตฌํ๋๋ ๊ณผ์ ์ ํ์
ํ๋๋ฐ ์๊ฐ์ด ์ข ์์๋์๋ค.
์๋์ ์ฝ๋์์๋ Prev, Next ๊ธ์๋ฅผ ๋๋ฅด๋ฉด ํ์ด์ง๊ฐ ์ด๋๋๋ ๋ฐฉ์์ด์๋๋ฐ,
์ฐ๋ฆฌ ํ๋ก์ ํธ ๋์์ธ์ ๋ง๊ฒ react-icons์ ์ฌ์ฉํด์ ์ด๋ถ๋ถ์ ๋จผ์ ์์ ํด์ฃผ์๋ค.
createPagination.js ํ์ผ์์ pagination์ด๋ผ๋ ๋ฐฐ์ด์ ๋ฐํํด์ค๋ค.
(์ด๋ถ๋ถ์ ๋ค์ ํฌ์คํ
์์ ์ค๋ช
)
pagination[0]์ ๊ฐ์ด 1์ธ ๊ฒฝ์ฐ,
์ผ์ชฝ ํ์ดํ(FaAngleLeft)๋ฅผ ํด๋ฆญ ๋ชปํ๊ฒ๋ className์ ์ด์ฉํด ์ค์ ํ๊ณ
์ค๋ฅธ์ชฝ ํ์ดํ(FaAngleRifht)๋ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ง์ง๋ง ํ์ด์ง๋ฅผ ํด๋ฆญํ ๊ฒฝ์ฐ,
ํ์ดํ๋ฅผ ํด๋ฆญ๋ชปํ๊ฒ๋ className์ ์ด์ฉํด ์ค์ ํด์ฃผ์๋ค.
(์ค๋ช ์ ํด๋นํ๋ ์ฝ๋๋ง ์๋์ ์ฒจ๋ถํ์๊ณ , ์ ์ฒด์ฝ๋๋ ๋งจ ๋ง์ง๋ง์ ์ค๋ช ๋์ด ์๋ค.)
const Ul = styled.ul`
.left {
margin-right: 5px;
cursor: pointer;
}
.right {
margin-left: 5px;
cursor: pointer;
}
.disabled {
color: #e0e0e0;
pointer-events: none;
}
`
<FaAngleLeft
className={`${pagination[0] === currentPage ? 'disabled left' : 'left'}`}
onClick={handleClick.bind(null, currentPage - 1)}
/>
<FaAngleRight
className={`${pagination.reverse()[0] === currentPage ? 'disabled right' : 'right'}`}
onClick={handleClick.bind(null, currentPage + 1)}
/>
์์ ์ฝ๋์์ ๋ณด๋ฉด onClick()
์ด๋ฒคํธ์ handleClick.bind()
๋ผ๋ ํจ์๋ฅผ ๋ณผ ์๊ฐ ์๋๋ฐ,
์ฒ์๋ณด๋ ํํ์ ์ฝ๋์๊ธฐ์ ๊ฒ์์ ํด๋ณด์๋ค.
MDN ์ฌ์ดํธ
Function.prototype.bind()
bind()
๋ฉ์๋๊ฐ ํธ์ถ๋๋ฉด ์๋ก์ด ํจ์๋ฅผ ์์ฑํฉ๋๋ค.
๋ฐ๊ฒ๋๋ ์ฒซ ์ธ์์ value๋ก๋ this ํค์๋๋ฅผ ์ค์ ํ๊ณ , ์ด์ด์ง๋ ์ธ์๋ค์ ๋ฐ์ธ๋๋ ํจ์์ ์ธ์์ ์ ๊ณต๋ฉ๋๋ค.
์ญ์ ์ฝ์ด๋ณด๋ ๊ฒ๋ง์ผ๋ก๋ ์ดํด๊ฐ ์๋ฒฝํ ๋์ง ์์ผ๋ฏ๋ก, ์์์ฝ๋๋ฅผ ๋ณด๋ฉด์ ์ฝ๋๋ฅผ ์ง๋ณด์๋ค.
const project = {
name: "donorticon",
getName: function () {
return this.name
}
}
์์ ๊ฐ์ด project
๋ผ๋ ๊ฐ์ฒด๋ฅผ ์ ์ธํด์ฃผ์๋ค. project
๋ด๋ถ์ ์ ์ธ๋ getName
๋ฉ์๋๋ฅผ ์๋์ ๊ฐ์ด ํธ์ถํด ๋ณด์๋ค.
const test1 = project.getName();
console.log(test1) // 'donorticon'
const test2 = project.getName;
console.log(test2()) // ''
const test3 = test2.bind(project);
console.log(test3()) // 'donorticon'
test1์ ๊ฒฝ์ฐ๋ ๋น์ฐํ ๊ฒฐ๊ณผ์ด๋ ๋ณ๋์ ์ค๋ช
์ ์๋ตํ๋ค.
test2์ ๊ฒฝ์ฐ ๋น ๊ฐ์ด ์ถ๋ ฅ๋๋๋ฐ, ๋น ๊ฐ์ด ์ถ๋ ฅ๋๋ ์ด์ ๋ฅผ ์ฐพ์๋ณด๋ ์๋์ ๊ฐ์๋ค.
์ธ์๋ก ์ ๋ฌ๋ฐ์ ํจ์๋ฅผ ํธ์ถํ๊ณ ์ ํ ๋, this์ window๋ฅผ ํ ๋นํ๋ค.
๋ฐ๋ผ์ ์ด ๊ฒฝ์ฐ์๋ this.name์ด window.name์ด ๋๋๋ฐ,
window ๊ฐ์ฒด์๋ name์ด ์์ผ๋ฏ๋ก ๋น ๊ฐ์ด ์ถ๋ ฅ๋๋ ๊ฒ์ด๋ค.
[์ฐธ๊ณ ๋ธ๋ก๊ทธ: ํจ์ ๋ฐ์ธ๋ฉ]
test3์ ๊ฒฝ์ฐ bind()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ this๊ฐ project
๋ฅผ ๊ฐ๋ฅดํค๋๋ก ํ ๊ฒ์ด๊ณ ,
์ํ๋ ๊ฐ์ ์ถ๋ ฅํ ์ ์์๋ค.
์ค์ ๊ตฌํ๋ ์ฝ๋๋ฅผ ์ดํด๋ณด๋ฉด, handleClick.bind(null, currentPage - 1)
์ ๊ฐ์ด
ํจ์ ์ธ์๋ฅผ 2๊ฐ๋ฅผ ๋๊ฒจ์ฃผ๊ณ ์๋ค. ์ด ๊ฒ์ ๋ ๋ฌด์์ผ๊น....? ๐ญ
MDN ์ฌ์ดํธ
๋ถ๋ถ ์ ์ฉ ํจ์
bind()
์ ๋ค์์ผ๋ก ๊ฐ๋จํ ์ฌ์ฉ๋ฒ์ ๋ฏธ๋ฆฌ ์ง์ ๋ ์ด๊ธฐ ์ธ์๊ฐ ์๋ ํจ์๋ฅผ ๋ง๋๋ ๊ฒ๋๋ค.
์ง์ ๋ ์ด๊ธฐ ์ธ์๊ฐ ์๋ค๋ฉด ์ ๊ณต๋this
๊ฐ์ ๋ฐ๋ฅด๊ณ , ๋ฐ์ธ๋ฉ ๋ ํจ์์ ์ ๋ฌ๋์ด ๋ฐ์ธ๋ฉ ๋ ํจ์๊ฐ ํธ์ถ๋ ๋๋ง๋ค ๋์ ํจ์์ ์ธ์ ์์ ์ฝ์ ๋ฉ๋๋ค.
์ด..์ด๋ฐ..??? ์...๐คฏ๐คฏ๐คฏ๐คฏ
์ผ๋จ MDN ์ฌ์ดํธ์ ์ ๊ณต๋ ์์ ์ฝ๋๋ฅผ ๋ณด๋ฉฐ ์ฝ๋๋ฅผ ์ง๋ณด์๋ค.
function list() {
return Array.prototype.slice.call(arguments);
}
const fixedValue = list.bind(null, 10);
console.log(fixedValue()) // [10]
console.log(fixedValue(100,200,300)) // [10, 100, 200, 300]
์ํ! 60% ์ ๋ ๊ฐ์ด ์จ ๊ฒ ๊ฐ๋ค.
bind()
์ ๋๋ฒ์งธ ์ธ์๋ก ์ด๊ธฐ๊ฐ์ ์ค์ ํด์ฃผ๊ณ , ๊ทธ ์ด๊ธฐ๊ฐ์ ์ ์ฅํด ๋ ์ ์๋ ๊ฒ ๊ฐ๋ค.
๊ทธ๋ฐ๋ฐ... Array.prototype.slice.call(arguments)
๋๋ ๋๊ตฌ๋?
(๊ฐ๋จํ ๊ฐ๋
๋ง ์๊ณ ๊ฐ์ ๐ง)
call()
์ ์์ context๋ฅผ ๋ณ๊ฒฝํ๋ ๋ฉ์๋์ด๊ณ ,
arguments
๋ ํจ์์ ๋งค๊ฐ๋ณ์์ ์ ๊ทผํ ์ ์๋ ์์ฑ์ด๋ค.
๊ฐ๋จํ ์ค๋ช ํ์๋ฉด, ํจ์์ ๋งค๊ฐ๋ณ์๋ก ๋์ด์จ ๊ฐ๋ค์ array๋ก ๋ณํํ๊ฒ ๋ค๋ ๊ฒ์ด๋ค.
[์ฐธ๊ณ ๋ธ๋ก๊ทธ: Array.prototype.slice.call(arguments) ์ ๋ํ์ฌ]
Pagination ์ฝ๋์ ์์ ์ด๋ก ๋ค์ ์ ์ฉํด ๋ณด์๋ฉด,
ํ์ฌ ๋ด๊ฐ ์๋ page ๊ฐ์ bind()
๋ฉ์๋๋ฅผ ํตํด ์ ์ฅํ ์ ์๋ ๊ฒ์ด์๋ค!
๐ฅณ๐ฅณ๐ฅณ
์ผ์ชฝ ํ์ดํ(FaAngleLeft)๋ฅผ ๋๋ฅด๋ฉด currentPage๊ฐ๋ณด๋ค 1์ด ์์์ง ํ์ด์ง๋ฅผ ์ ์ฅํ๊ณ ,
ํ์ด์ง ์ซ์๋ฅผ ๋๋ฅด๋ฉด, ๊ทธ ํ์ด์ง ์ซ์๋ฅผ ์ ์ฅํ๊ณ ,
์ค๋ฅธ์ชฝ ํ์ดํ(FaAngleRight)๋ฅผ ๋๋ฅด๋ฉด currentPage๊ฐ๋ณด๋ค 1์ด ์ปค์ง ํ์ด์ง๋ฅผ ์ ์ฅํ๊ฒ ๋๋ค.
const handleClick = (page) => {
setCurrentPage(page);
}
// ์ค๊ฐ ์ฝ๋ ์๋ต
<FaAngleLeft
// ์ฝ๋ ์๋ต
onClick={handleClick.bind(null, currentPage - 1)} />
{pagination.map((page, idx) => (
<li
// ์ฝ๋ ์๋ต
onClick={handleClick.bind(null, page)} />
{page}
</li>
))}
<FaAngleRight
// ์ฝ๋ ์๋ต
onClick={handleClick.bind(null, currentPage + 1)} />
์ด์ bind()
๋ฉ์๋์ ๋ํ ๊ฐ๋
์ ์ด๋์ ๋ ์กํ ๊ฒ ๊ฐ๋ค.
๊ทธ๋ฐ๋ฐ...์ด ์์ ์์ ํ๊ฐ์ง ์๋ฌธ์ด ๋ค์๋ค.
bind()
๋ฉ์๋๋ ๊ผญ ํ์ํ ๋ฉ์๋์ธ๊ฐ? bind()
๋ฉ์๋ ์์ด ์ฝ๋ ๊ตฌํํ ์ ์์ง ์์๊น?
bind()
์ ๊ฑฐ์ผ๋จ ๊ฐ๊ฐ ์์๋ค์ onClick()
๋ถ๋ถ์ bind()
๋ฅผ ์ ๊ฑฐํ๋ค.
onClick={handleClick(currentPage - 1)}
onClick={handleClick(page)}
onClick={handleClick(currentPage + 1)}
๊ทธ๋ฌ๋๋ ์๋์ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
ํด๋น ์๋ฌ์ ๋ํด์ ๊ฒ์์ ํด๋ณด๋,
onClick()
์ด๋ฒคํธ์๋ง ํจ์๊ฐ ํธ์ถ๋๋ ๊ฒ์ด ์๋๋ผ,
render ๋ ๋๋ง๋ค ํจ์๋ฅผ ํธ์ถํ๊ธฐ ๋๋ฌธ์ ๋ฌดํ ๋ฃจํ๊ฐ ๋ฐ์ํ๋ค๋ ๊ฒ์ด์๋ค.
[์ฐธ๊ณ ๋ธ๋ก๊ทธ: [React] Error: Maximum update depth exceeded... ์ค๋ฅ ํด๊ฒฐ๋ฒ]
๊ทธ๋์ ์๋์ ๊ฐ์ด ์ฝ๋๋ฅผ ์์ ํด ์ฃผ์๋ค.
onClick={() => handleClick(currentPage - 1)}
onClick={() => handleClick(page)}
onClick={() => handleClick(currentPage + 1)}
๋ฐ๋ค๋จ ๐ ์๋ฌ๋ฉ์ธ์ง๋ ์ฌ๋ผ์ก๊ณ , Pagination ๊ธฐ๋ฅ๋ ๋ฌธ์ ์์ด ์ ์๋ํ๋ ๊ฒ์ ํ์ธํ๋ค!
<<
๋ฒํผ์ ๋๋ฅด๋ฉด ์ด๋ ํ์ด์ง์ ์๋ 1ํ์ด์ง๋ก ์ด๋ํ๊ณ ,
>>
๋ฒํผ์ ๋๋ฅด๋ฉด ์ ์ผ ๋ง์ง๋ง ํ์ด์ง๋ก ์ด๋ํ ์ ์๊ฒ ์์ด์ฝ์ ์ถ๊ฐํ๋ค.
<FaAngleDoubleLeft
size="18"
className={`${
pagination[0] === currentPage ? 'disabled left' : 'left'}`}
onClick={() => handleClick(1)}
/>
<FaAngleDoubleRight
size="18"
className={`${pagination[0] === currentPage ? 'disabled right' : 'right'}`}
onClick={() => handleClick(maxPage)}
/>
๋ ์์ ์นญ์ฐฌํ๋ค... ๐๐ป๐๐ป๐๐
import {
FaAngleLeft,
FaAngleRight,
FaAngleDoubleLeft,
FaAngleDoubleRight,
} from 'react-icons/fa';
import {
PaginationContainer,
PaginationUl,
} from '../../styles/PaginationStyle';
import createPagination from './createPagination';
const Pagination = ({ maxPage, currentPage, setCurrentPage }) => {
const { pagination } = createPagination({
numberOfPage: 5,
currentPage,
maxPage,
});
const handleClick = (page) => {
setCurrentPage(page);
};
return (
<PaginationContainer>
<PaginationUl>
<FaAngleDoubleLeft
size="18"
className={`${
pagination[0] === currentPage ? 'disabled left' : 'left'
}`}
onClick={() => handleClick(1)}
/>
<FaAngleLeft
size="18"
className={`${
pagination[0] === currentPage ? 'disabled left' : 'left'
}`}
onClick={() => handleClick(currentPage - 1)}
/>
{pagination.map((page, idx) => (
<li
key={idx}
className={`${currentPage === page && 'active'}`}
onClick={() => handleClick(page)}
>
{page}
</li>
))}
<FaAngleRight
size="18"
className={`${
pagination.reverse()[0] === currentPage ? 'disabled right' : 'right'
}`}
onClick={() => handleClick(currentPage + 1)}
/>
<FaAngleDoubleRight
size="18"
className={`${
pagination[0] === currentPage ? 'disabled right' : 'right'
}`}
onClick={() => handleClick(maxPage)}
/>
</PaginationUl>
</PaginationContainer>
);
};
export default Pagination;
createPagination.js ํ์ผ์ ๋ํ ์ค๋ช ์ ๋ค์ ํฌ์คํ ์ ์ด์ด์ ํ๊ฒ ๋ค. ๐ฅธ