일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- React
- 티스토리챌린지
- exceljs
- 오블완
- threejs
- 블록체인
- 라라벨
- chatGPT
- jquery
- 공연티켓
- pagination
- nginx
- Remix
- metamask
- miniconda
- Laravel
- NextJS
- PM2
- node
- 배포
- nft
- Kaikas
- nodejs
- polygon
- Ai
- Python
- CSS
- netfunnel
- Setting
- 회고
- Today
- Total
박주니 개발 정리
react redux를 이용해서 pagination 활용 본문
1. 먼저 redux 패키지를 설치합니다.
npm install redux react-redux
참고 파일구조
2. store 폴더를 생성하고 index.js에 redux 스토어를 생성하고 애플리케이션에 redux를 통합합니다.
// src/store/index.js
import { createStore } from "redux";
import { combineReducers } from "redux";
import paginationReducer from "./reducers/paginationReducer";
// 리듀서를 복수로 관리하려면 combineReducers 함수를 사용하여 하나의 루트 리듀서로 결합합니다.
const rootReducer = combineReducers({
pagination: paginationReducer,
});
const store = createStore(rootReducer);
export default store;
추가 설명
이부분에서는 reducer을 createStrore 기능만 한다고 보시면 됩니다.
3. reducers 폴더를 생성하고 paginationReducer.js를 만든 다음 페이지 관련 reducer을 만듭니다.
// src/store/reducers/paginationReducer.js
import { SET_CURRENT_PAGE, SET_ASSET } from "../actions/paginationActions";
const initialState = {
currentPage: 1,
asset: null,
};
const paginationReducer = (state = initialState, action) => {
switch (action.type) {
case SET_CURRENT_PAGE:
return {
...state,
currentPage: action.payload,
};
case SET_ASSET:
return {
...state,
asset: action.payload,
};
default:
return state;
}
};
export default paginationReducer;
추가 설명
- const initialState = {currentPage: 1, asset: null}
여기서 asset은 추후에 정보를 가지고 왔을 때 페이지를 넘길 시 보여줄 정보를 관리하기 위해 구분을 해놨는데 그것보다 currpentPage를 설명을 드리면
const {currentPage, setCurrentPage} = useState(1);
의미 합니다. 어차피 redux 사용하지 않고 프론트에서 직접 다 구현한다고 생각했을 때 어떻게 전달되는 지 이해하시면 쉽게 접근하실 수 있을것입니다.
- paginationReducer
단순하게
setCurrentPage(...currentPage, action.payload)
입니다. 즉 초기 설정을 1로 설정을 했는데 프론트에서 action을 거쳐서 변경할 값을 받게 되면 그 값으로 교체되거나 추가가 됩니다. 배열 형식을 경우에는 추가가 될 것이고 지금처럼 배열이 아닐 경우 교체가 될 것입니다.
4. actions 폴더를 생성하고 paginationActions.js를 만든 다음 액션 생성자 함수를 작성합니다.
// src/store/actions/paginationActions.js
export const SET_CURRENT_PAGE = "SET_CURRENT_PAGE";
export const SET_ASSET = "SET_ASSET";
export const setCurrentPage = (page) => {
return {
type: SET_CURRENT_PAGE,
payload: page,
};
};
export const setAsset = (asset) => {
return {
type: SET_ASSET,
payload: asset,
};
};
추가 설명
먼저 이 코드 설명 앞서서 3번 reducer을 보면 paginationActions를 import 한 것을 볼 수 있을 것입니다. 프론트에서 dispatch로 받은 값을 action에서 type으로 구분하고 reducer에 보내서 값을 관리한다고 보시면 됩니다.
5. App.js에 Provider을 통해 store 연결해서 애플리케이션 redux 적용하시면 됩니다.
import React from 'react';
import { Provider } from 'react-redux';
import store from './store';
import Pagination from './components/Pagination';
const App = () => {
return (
<Provider store={store}>
<div className="App">
</div>
</Provider>
);
};
export default App;
6. 프론트에 react-redux import 해서 useSelector, useDispatch를 이용해서 값을 dispatch를 해서 set하거나 selector을 이용해서 값을 가지고 온다는 관점에서 pagination을 만드시면 됩니다.
import { React, useState } from "react";
// redux
import { useSelector, useDispatch } from "react-redux";
import {
setCurrentPage,
} from "../../../../store/actions/paginationActions";
function TotalTicketList() {
let [totalPage, setTotalPage] = useState(100);
// redux
const currentPage = useSelector((state) => state.pagination.currentPage);
const asset = useSelector((state) => state.pagination.asset);
const dispatch = useDispatch();
const rowsPerPage = 20; // 한 페이지에 보여지는 로우의 개수
const handlePageChange = (page) => {
dispatch(setCurrentPage(page));
};
const renderPaginationButtons = () => {
const totalPages = Math.ceil(totalPage / rowsPerPage);
const visibleButtons = 10; // 한 번에 보여질 숫자 버튼의 개수
const firstVisiblePage =
Math.floor((currentPage - 1) / visibleButtons) * visibleButtons + 1;
const lastVisiblePage = Math.min(
firstVisiblePage + visibleButtons - 1,
totalPages
);
const buttons = [];
for (let i = firstVisiblePage; i <= lastVisiblePage; i++) {
buttons.push(
<span
key={i}
onClick={() => handlePageChange(i)}
className={currentPage === i ? "active" : ""}
>
{i}
</span>
);
}
return buttons;
};
return (
<div className="pagination">
<button
onClick={() => handlePageChange(currentPage - 1)}
disabled={currentPage === 1}
>
이전
</button>
{renderPaginationButtons()}
<button
onClick={() => handlePageChange(currentPage + 1)}
disabled={
currentPage === Math.ceil(totalPage / rowsPerPage)}
>
다음
</button>
</div>
);
}
export default TotalTicketList;
- react-redux에서 useSelector, useDispatch를 가지고 오고 paginationActions에서 setCurrentPage를 가지고 옵니다.
- return 안에 페이지네이션 셋팅을 합니다.
- renderPaginationButtons 함수에 페이지네이션 버튼 조건문을 만듭니다.
- firstVisiblePage : Math.floor 을 이용해서 Math.floor((currentPage -1)/visibleButtons))을 했을 때 예를 들어서 currentPage가 5이고 visibleButtons가 10일 때 0.4의 값이 나오면 버림을 했을 경우 0이 되고 visibleButtons의 값을 곱하고 1로 더하면 값은 1이 되는 것을 볼 수 있습니다.
- lastVisiblePage : Math.min은 가장 최소 값을 내보내는 내장 함수입니다.여러 조건문으로 남은 값이 10미만 여부를 따라서 조건문을 작성해 코드가 중복될 수 있었는데 이 함수를 이용하면 한줄로 체크할 수 있습니다.
- 회고: 저는 이 방식을 몰랐을 때에는 페이지네이션 체크 숫자 따로 다음 페이지로 넘어갈 때 10보다 크거나 작거나 같은 경우에 따른 조건문을 다 작성해서 구현하다보니 rendering 함수 따로 movePage 함수 따로 만들어서 30줄이면 끝날 수 있는 것을 150줄 이상을 작성하게 되었습니다. 그래도 어떻게 돌아가는 지 확실히 알게 되어서 좋은 경험이었습니다.
- handlePageChange 함수를 통해서 paginationActions에 page를 dispatch를 합니다.
- 추가 설명 - 여기서 dispatch는 actions에 값을 전달하는 것을 도와주는 개념이고 실질적으로는 setCurrentPage에 매개변수로 page를 전달해서 type: SET_CURRENT_PAGE에 payload가 전달한 page값을 넣습니다. 그 다음 그 값을 reducer에서 변경된 값을 넣습니다.
- useSelector을 통해서 변경된 page값을 가지고 옵니다.
const currentPage = useSelector((state) => state.pagination.currentPage);
추가 설명 - 값을 가지고 올때 state.pagination.currentPage로 한 이유는 index.js에서 reducer을 생성할 때 pagination으로 combine을 했고 reducer에서 payload 값이 currentPage에 있기 때문에 거기서 값을 가지고 온다고 보시면 됩니다.
tip)
- index.js - rootReducer 구성 확인
- paginationActions에서 setCurrentPage type은 SET_CURRENT_PAGE로 해서 paginationReducer 전달
- paginationReducer에서 type 확인 후 return action.payload 값 전달