Posts [React] 리액트 페이지네이션(pagination) 구현하기 (1)
Post
Cancel

[React] 리액트 페이지네이션(pagination) 구현하기 (1)


리액트 페이지네이션 구현하기(React pagination) (1)


🚩 페이지네이션

웹 페이지에서 게시판 밑에 보면 1, 2, 3, 4,… 로 페이지 번호를 매겨 놓은 모습을 아주 흔하게 보실 수 있습니다.

(출처 : 다음 뉴스 게시판)

이러한 페이지네이션을 React hook인 useState, useEffect와 자바스크립트 array 메소드인 slice를 활용해 간단하게 구현하는 방법을 알아보겠습니다.


📘 1. 리액트 프로젝트 생성

리액트 프로젝트 관련 설정 및 초기 생성법 : https://chanhuiseok.github.io/posts/react-2/

아래 명령어를 통해 리액트 프로젝트를 생성합니다.

1
$ yarn create react-app myDirName

생성 후 해당 디렉토리로 이동합니다.

1
$ cd myDirName

📘 2. 연습용 데이터 가져오기

일단 불필요한 파일들은 먼저 삭제해 보겠습니다. 생성한 리액트 프로젝트에서 아래 파일들을 삭제해 주세요.

App.test.js, reportWebVitals.js, setupTests.js

온라인에서 별도의 키값이 없어도 연습용으로 REST API를 제공하는 사이트가 많습니다.

그 중에서 저는 https://jsonplaceholder.typicode.com/ 사이트를 사용하겠습니다.

사용할 주소 : https://jsonplaceholder.typicode.com/posts

이 주소에 접속해 보면 위와 같이 100개의 데이터를 json 형태로 받아옴을 확인할 수 있습니다.

이제 App.js에 들어가서 코드를 수정합니다. 그 전에, axios와 styled-components 먼저 설치합니다.

1
2
$ yarn add axios
$ yarn add styled-components

axios는 자바스크립트에서 Promise를 기반으로 하여 비동기 처리를 도와줍니다. axios는 받아온 json 데이터를 알아서 변환해 주기도 하고, 크로스 브라우징에서도 효과적이어서 많이 쓰인다고 합니다.

styled-components는 리액트에서 CSS-in-JS를 실현하게 해 주는 라이브러리입니다. 여기서도 간단하게 컴포넌트 단위의 디자인을 설정하기 위해 설치하였습니다.


이제 App.js 코드를 수정합니다. 데이터를 잘 받아오는지 테스트 하는 과정입니다.

아래에서 사용한 hook 및 각종 함수들에 대한 설명은 하단에 작성하였습니다.

useState hook 알아보기 : https://chanhuiseok.github.io/posts/react-6/

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
import './App.css';
import React, { useState, useEffect } from 'react';
import axios from 'axios';

function App() {
  const [posts, setPosts] = useState([]);
  const [loading, setLoading] = useState(false);
  const [currentPage, setCurrentPage] = useState(1);
  const [postsPerPage, setPostsPerPage] = useState(10);

  useEffect( () => {
    async function fetchData() {
      setLoading(true);
      const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
      setPosts(response.data);
      setLoading(false);
    }
    fetchData();
  },[]);

  console.log(posts);

  return (
    <div className="App">
      
    </div>
  );
}

export default App;

  • App은 함수형 컴포넌트로 작성되었습니다. 따라서, useState나 useEffect와 같은 hook을 사용한 것입니다.
  • (6~9행) posts, loading, currentPage, postsPerPage state를 지정하였습니다. posts state에는 실제 json 데이터들이 array 형태로 들어오므로 초기값을 배열 리터럴([])로 두었습니다.
  • (11~18행) useEffect hook을 작성한 모습입니다.
    • (12~16행) async, await, axios로 데이터를 가져오는 모습입니다. useEffect hook은 특정한 작업을 렌더링(마운트)할 때마다 사용할 경우 사용합니다. 첫 번째 인자에 작성한 함수를 작업으로 실행합니다. 두 번째 인자에 [] 를 두었는데, 이렇게 하면 컴포넌트가 맨 처음 렌더링(마운트)될 때만 정의한 함수를 실행하고, 업데이트 될 때는 실행하지 않습니다.
    • 익명 함수 앞에 async를 붙여서 이 부분은 비동기 처리를 하는 곳이라고 알립니다. 밑에서 axios.get 이 반환하는 것은 Promise 객체인데요, 그 앞에 await를 붙여서 프로미스가 반환될 때까지 기다립니다.
    • 이를 기다리는 동안 자바스크립트 엔진은 다른 일들을 처리할 수 있습니다. 그래서 비동기 처리를 도와주는 문법이라는 것입니다.
    • 참고로, await은 반드시 async로 정의한 함수 내부에서만 사용할 수 있습니다.
    • async, await 구문은 promise 객체가 .then으로 콜백을 처리하던 부분을 좀 더 깔끔하게 작성할 수 있게 해 줍니다.
    • 받아온 데이터를 setPosts 를 통해 posts state에 넣어주었습니다.

브라우저 콘솔에 데이터가 뜨는지 확인해 볼까요?

이렇게 100개의 포스트를 정상적으로 받아온 것을 확인할 수 있습니다.


📘 3. 페이지에 내용을 표시하기

받아온 데이터를 콘솔이 아니라 웹 페이지에 표시해 보려고 합니다.

리액트에서 컴포넌트 단위로 작성하는 방법을 연습하기 위해, 데이터가 표시되는 컴포넌트를 Posts로 정의하여 간단하게 작성해 보겠습니다.

📜 Posts.js 생성 및 작성

React map 함수 사용법 : https://chanhuiseok.github.io/posts/react-8/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React from 'react';

const Posts = ({ posts, loading }) => {
  return (
    <>
  { loading &&
    <div> loading... </div>
  }
  <ul>
    { posts.map(post=>(
      <li key={post.id}>
        {post.title}
      </li>
    ))}
  </ul>
  </>
  );
};
export default Posts;
  • Posts 컴포넌트는 인자로 posts, loading을 넘겨받습니다.
  • posts는 데이터이고, loading은 데이터가 아직 로딩되지 않았을 경우를 처리합니다.
    • { loading && … } 부분은, loading 값이 true일 때 && 다음의 것을 표시한다는 의미입니다.
  • 자바스크립트의 map 함수를 사용하여 여러 데이터들을 표시합니다. posts 라는 배열에 담긴 값을 하나씩 post로 빼와서 <li> 로 만들어 보여 줍니다.
  • 이 때 map 함수로 여러 요소를 그릴 때는, 해당 요소에 key 값을 사용해야 합니다. 데이터에서 키로 구분이 될 만한 값은 id 입니다. 따라서 그려주는 요소에 key를 {post.id} 값으로 전달한 것입니다.

📜 App.js 수정

위에서 만든 Posts 컴포넌트를 사용합니다. Posts 를 import 하고, return문 안에서 사용합니다.

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
import './App.css';
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import Posts from './Posts'

function App() {
  const [posts, setPosts] = useState([]);
  const [loading, setLoading] = useState(false);
  const [currentPage, setCurrentPage] = useState(1);
  const [postsPerPage, setPostsPerPage] = useState(10);

  useEffect( async() => {
    setLoading(true);
    const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
    setPosts(response.data);
    setLoading(false);
  },[]);

  console.log(posts);

  return (
    <div className="App">
      <Posts posts={posts} loading={loading}></Posts>
    </div>
  );
}

export default App;

다시 실행해 보면 웹 페이지에 아래와 같이 데이터가 출력됩니다.

이제 이 데이터들을 정해진 페이지단위에 맞게 페이지네이션을 하는 작업만 남았습니다.

다음 포스팅에서 이어서 작성하겠습니다!


JavaScript - 자바스크립트 실행 컨텍스트, 스코프(Scope), 스코프 체인

[React] 리액트 페이지네이션(pagination) 구현하기 (2)