본문 바로가기
언어/React

[React] useEffect, useRef, pagination 구현 사례

by 김뱅쓰 2023. 2. 27.

useeffect : 무언가 변화가 있을 때 감지하여 반응하는 Hook

import './App.css';
import { useEffect, useState } from "react";

function App() {
  const [count, setCount] =useState(0);

  useEffect(()=>{
    console.log(`Clicked ${count} times`);
  },[count]); // count의 변화를 감지한다.

  useEffect(()=> {
    console.log("Component Loaded");
    const handleScroll = () => {
      console.log(window.scrollY);
    };

    document.addEventListener("scroll" , handleScroll); //전역적인 이벤트를 사용할 때 쓸 수 있다.
    return () => document.removeEventListener("scroll", handleScroll); //return으로 변환한 함수는 컴포넌트가 제거될 때 실행된다.
  }, []); //컴포넌트가 처음으로 로드될 때 실행된다.

  return (
    <div>
      <div>You clicked {count} times.</div>
      <button onClick={() => setCount(count + 1)}>+</button>

      <div style={{height: 10000}}></div>
    </div>
  )
  
}

export default App;

 

 

react app
개발자 모드

 

 

useRef

1. 돔에 직접 접근할 때 사용한다.

2. 지역 변수로 사용할 때 사용한다.

useState 는 값이 변경될 때 다시 렌더링을 한다.

useRef는 값이 변경되더라도 다시 렌더링을 하지 않는다.

Auto counter 만들어보기

import { useState, useRef } from "react";

const AutoCounter = () => {
    const [count, setCount] = useState(0);
    const intervalId = useRef();

    const handleStart = () => {
       intervalId.current = setInterval(() => {
        setCount((count) => count +1);
       }, 1000);
    };

    const handleStop = () => {
        clearInterval(intervalId.current);
    };

    return (
        <>
        <div>{count}</div>
        <button onClick={handleStart}>Start</button>
        <button onClick={handleStop}>Stop</button>
        </>
    )
}

export default AutoCounter;

페이지네이션

게시판같은 리스트를 보여주는

 

import { useState } from 'react';
import Board from './components/Board/Board';
import Pagination from './Pagination.js';

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;

app.js

 

import PropTypes from "prop-types";
const Board = ({articles}) => {
    return (
        
            <ul>
               {articles.map(articles => (
                <li key={articles.id}>
                    {articles.id} || {articles.title} |{articles.author}
                </li>
               ))}
            </ul>
    );
};

Board.propTypes ={
    articles: PropTypes.array
}

export default Board;

board.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;

pagination.js

 

react