본문 바로가기
토이 프로젝트/서울시문화행사

React로 웹페이지 만들기 - 서울시 문화행사(4)

by 강물둘기 2023. 3. 6.

Pagination 버튼 구현

앞에서 상태를 저장할 store를 만들고 상태를 꺼내와서 쓰는 것을 적용시켜보았는데 이번에는 상태를 사용하면서 이벤트가 일어났을 때 액션 객체를 보내서 상태를 변경시키는 연습겸 구현하는 작업을 진행하였다.

현재 페이지 상태를 만들고 현재 페이지 상태를 변경시키는 Reducer 를 만들고 Pagination 버튼을 구현해 보았다. 

 

State, Reducer

일단 createSlice 메서드로 현재 페이지 상태와 reducer를 만들어 보았다.

// itemSlice.js
export const currentPageSlice = createSlice({
  name: "currentPage",
  initialState: { value: 1 },
  reducers: {
    prevPage: (state) => {
      state.value--;
    },
    nextPage: (state) => {
      state.value++;
    },
    somePage: (state, action) => {
      state.value = action.payload;
    },
  },
});
export const { prevPage, nextPage, somePage } = currentPageSlice.actions;

이전과 동일하게 이름과 초기값을 지정해주고, reducer 프로퍼티에 reducer들을 만들면된다.

버튼은 총 3가지로 이전 페이지 버튼, 다음 페이지 버튼, 그리고 특정 페이지 클릭시 해당 페이지로 이동하는 버튼이다.

페이지 컴포넌트는 숫자로 유지되기 때문에 해당 reducer가 발동하면 알맞는 동작을 등록하면 된다.

* dispatch로 action 객체를 전달하면 전달내용은 action객체의 payload 프로퍼티에 저장되어 전달되기 떄문에 해당 페이지로 이동할 때 state.value = action.payload로 할당한다.

 

그리고 만들어진 reducer들을 사용하기위해 export 해줘야 하는데 이 reducer들은 createSlice메서드에 의해 자동으로 해당 slice의 actions 프로퍼티에 저장된다. 따라서 구조분해할당으로 actions 프로퍼티 내부의 세 가지 reducer들을 export해서 필요한 컴포넌트에 import하여 사용하면 된다.

 

Pagination 컴포넌트

Pagination.js 컴포넌트를 만들고 pagination을 위한 기본 코드를 작성했다.

// Pagination.js
import { useSelector, useDispatch } from "react-redux";
import { prevPage, nextPage, somePage } from "../itemSlices";

const Pagination = () => {
  const { value: currentPage } = useSelector((state) => state.currentPage);
  const dispatch = useDispatch();
  const total = 100;
  const limitItems = 6;
  const maxPages = Math.ceil(total / limitItems);
  const pageButtons = Array(10).fill();

  return (
    <div>
      <button
        className="button prev"
        disabled={currentPage === 1}
        onClick={() => {dispatch(prevPage());}}
        >
        {"<-"}
      </button>
      {pageButtons.map((_, i) => {
        i = i + 10 * Math.floor((currentPage - 1) / 10);
        return (
          <button
            className={`button ${i + 1 === currentPage ? "active" : ""}`} // 현재 페이지 활성화
            key={i + 1}
            onClick={() => {
              dispatch(somePage(i + 1));
            }}
            disabled={i >= maxPages}
          >
            {i + 1}
          </button>
        );
      })}
      <button
        className="button next"
        disabled={currentPage === maxPages}
        onClick={() => {dispatch(nextPage());}}
      >
        {"->"}
      </button>
    </div>
  );
};

export default Pagination;

페이지 상태는 useSelector로 꺼내오고,  reducer들을 import해와서 적용시켰다.

아직 필터링된 item들이 없어서 임시로 총 개수100개, 페이지당 개수 6개를 적용하여 pagination을 구현했다.

각각의 버튼에 이전에 만들었던 현재 페이지 상태를 변경하는 reducer들을 onClick 이벤트로 등록했다. 현재 페이지는 추가 className이 붙도록 조건을 작성해주었다.

 

reducer들이 잘 작동해서 상태가 잘 바뀐다. 

나중에 현재 페이지 상태과 해당 페이지 item 목록을 연동하기만 하면 될 것 같다.

 

메인페이지

메인페이지가 허전해보여서 일단은 더미 데이터로 적당히 구조를 잡아놓았다.

 

일단 배운것들은 잘 적용시켜본 것 같다. 다음으로는 데이터들을 필터링 하는 기능을 구현해볼 예정이다. 

 

 

 

 

댓글