리액트로 pagination 구현하기

나혜수·2023년 3월 20일
0

리액트

목록 보기
8/23

1. 카운터 구현

무엇을 학습할 것인가?

  • 컴포넌트에서 지역 상태 관리하는 법
  • 컴포넌트에 이벤트 바인딩하기
  • 부모 컴포넌트에게 메세지 전달하기

구현 요구사항

  • 카운터 컴포넌트 구현하기
  • 모든 카운터 컴포넌트의 합 구하기

코드

Counter.js

import { useState } from "react";
import PropTypes from 'prop-types'

const Counter = ({onIncrease, onDecrease}) => {
  const [count, setCount] = useState(0)

  const handleIncrease = () => {
    setCount(count + 1)
    if(onIncrease){
      onIncrease()
    }
  }

  const handleDecrease = () => {
    setCount(count - 1)
    if(onDecrease){
      onDecrease()
    }
  }

  return (
    <div>
      <p>현재 카운터 값은 {count}입니다.</p>
      <button onClick={handleIncrease}>+1</button>
      <button onClick={handleDecrease}>-1</button>
    </div>
  );
}

Counter.propTypes = {
  onChange: PropTypes.func
}


export default Counter;

App.js

import React, {useState} from 'react';
import Counter from './Counter';

function App() {
  const [totalCount, setTotalCount] = useState(0)

  return (
    <div>
      Total Count : {totalCount}
      <Counter 
        onIncrease={()=>setTotalCount(totalCount+1)}
        onDecrease={()=>setTotalCount(totalCount-1)}  
      ></Counter>
      <Counter 
        onIncrease={()=>setTotalCount(totalCount+1)}
        onDecrease={()=>setTotalCount(totalCount-1)}  
      ></Counter>
      <Counter 
        onIncrease={()=>setTotalCount(totalCount+1)}
        onDecrease={()=>setTotalCount(totalCount-1)}  
      ></Counter>
    </div>
  );
}

export default App;


2. pagination 구현

pagination
콘텐츠를 여러 개 페이지에 나눠서 보여주는 UI이다.

구현 요구사항

  • 글을 10개 단위로 끊어 페이지에 출력시킨다.
  • 이전, 이후, 숫자 버튼을 클릭하면 해당하는 번호의 게시물을 보여준다.
  • 포커싱 된 인덱스의 버튼은 빨간색으로 표시된다.
  • 한 번에 보이는 숫자 버튼은 5개로 고정된다. (해당 숫자 ∓ 2) 해당 숫자를 중심으로 이전 or 이후 숫자가 2개 미만이면 가장 가까운 숫자 5개를 보여준다.

코드

Board.js

import React from "react";
import PropTypes from 'prop-types'

const Board = ({articles}) => {
    return (
        <div>
            {articles.map(article =>
                <li key={article.id}>{article.id} | {article.title}</li>)}
        </div>
    )
}

Board.propTypes = {
    articles: PropTypes.array
}

export default Board

Pagination.js

import { useState } from "react"

const Pagination = ({defaultPage, limit, total, onChange}) => {
    const [page, setPage] = useState(defaultPage)
    const totalPage = Math.ceil(total/limit) // 올림 함수 

    const handleChangePage = (newPage) => {
        onChange(newPage)
        setPage(newPage)
    }

    return (
        <div>
            <button onClick={() => page !== 0  && handleChangePage(page-1)}>이전</button>
            {Array.from(new Array(totalPage),(_,i) => i).filter(i =>{ 
                if(page < 3){return i < 5}
                else if(page > totalPage -3){return i >= totalPage -5}
                return i >= page -2 && i <= page +2}).map(i => (
                <button key={i} 
                onClick= {()=>{handleChangePage(i)}}
                style={{backgroundColor: page === i ? 'red' : undefined}}>{i+1}</button>
            ))}
            <button onClick={() => page+1 !== totalPage && handleChangePage(page+1)}>이후
			</button>
        </div>
    )
}

export default Pagination

App.js

import React, {useState} from 'react';
import Board from './Board';
import Pagination from './Pagination';

/* Pagination 컴포넌트와 Board 컴포넌트가 어떤식을 통신하는지? 
   App 컴포넌트를 통해 데이터를 주고 받는다! */
// Pagination 로직 

function App() {
  const [page, setPage] = useState(0)
  const articles = new Array(100).fill().map((_,i) => ({
    id: i,
    title: `${i}번째 게시물`
  }))

  const limit = 10
  const offset = page + limit

  return (
    <div>
      <Pagination defaultPage={0} limit={10} total={articles.length}
      onChange={setPage}/>
      <Board articles={articles.slice(offset,offset+limit)}/>
    </div>
  );
}

export default App;

결과

profile
오늘도 신나개 🐶

0개의 댓글